diff options
-rw-r--r-- | Eyes.c | 168 | ||||
-rw-r--r-- | Eyes.h | 2 | ||||
-rw-r--r-- | EyesP.h | 15 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | xeyes.c | 8 |
6 files changed, 197 insertions, 6 deletions
@@ -63,6 +63,9 @@ static XtResource resources[] = { goffset(height), XtRImmediate, (XtPointer) 100}, {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(pixel[PART_PUPIL]), XtRString, XtDefaultForeground}, + {XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap), + XtOffsetOf(CoreRec,core.background_pixmap), + XtRImmediate, (XtPointer)None}, {XtNoutline, XtCForeground, XtRPixel, sizeof(Pixel), offset(pixel[PART_OUTLINE]), XtRString, XtDefaultForeground}, {XtNcenterColor, XtCBackground, XtRPixel, sizeof (Pixel), @@ -77,6 +80,10 @@ static XtResource resources[] = { {XtNrender, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(render), XtRImmediate, (XtPointer) TRUE }, #endif +#ifdef PRESENT + {XtNpresent, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(present), XtRImmediate, (XtPointer) TRUE }, +#endif {XtNdistance, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(distance), XtRImmediate, (XtPointer) FALSE }, }; @@ -113,6 +120,129 @@ static void ClassInitialize(void) WidgetClass eyesWidgetClass = (WidgetClass) &eyesClassRec; +#ifdef PRESENT +static void CheckPresent(EyesWidget w) { + const xcb_query_extension_reply_t *xfixes_ext_reply; + const xcb_query_extension_reply_t *damage_ext_reply; + const xcb_query_extension_reply_t *present_ext_reply; + xcb_xfixes_query_version_cookie_t xfixes_cookie; + xcb_xfixes_query_version_reply_t *xfixes_reply; + xcb_damage_query_version_cookie_t damage_cookie; + xcb_damage_query_version_reply_t *damage_reply; + xcb_present_query_version_cookie_t present_cookie; + xcb_present_query_version_reply_t *present_reply; + + if (!w->eyes.present) + return; + + xcb_prefetch_extension_data(xt_xcb(w), &xcb_xfixes_id); + xcb_prefetch_extension_data(xt_xcb(w), &xcb_damage_id); + xcb_prefetch_extension_data(xt_xcb(w), &xcb_present_id); + + xfixes_ext_reply = xcb_get_extension_data(xt_xcb(w), &xcb_xfixes_id); + damage_ext_reply = xcb_get_extension_data(xt_xcb(w), &xcb_damage_id); + present_ext_reply = xcb_get_extension_data(xt_xcb(w), &xcb_present_id); + if (xfixes_ext_reply == NULL || !xfixes_ext_reply->present + || damage_ext_reply == NULL || !damage_ext_reply->present + || present_ext_reply == NULL || !present_ext_reply->present) + { + w->eyes.present = FALSE; + } + + if (!w->eyes.present) + return; + + /* Now tell the server which versions of the extensions we support */ + xfixes_cookie = xcb_xfixes_query_version(xt_xcb(w), + XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + + damage_cookie = xcb_damage_query_version(xt_xcb(w), + XCB_DAMAGE_MAJOR_VERSION, + XCB_DAMAGE_MINOR_VERSION); + + present_cookie = xcb_present_query_version(xt_xcb(w), + XCB_PRESENT_MAJOR_VERSION, + XCB_PRESENT_MINOR_VERSION); + + xfixes_reply = xcb_xfixes_query_version_reply(xt_xcb(w), + xfixes_cookie, + NULL); + free(xfixes_reply); + + damage_reply = xcb_damage_query_version_reply(xt_xcb(w), + damage_cookie, + NULL); + free(damage_reply); + + present_reply = xcb_present_query_version_reply(xt_xcb(w), + present_cookie, + NULL); + free(present_reply); +} + +static void MakePresentData(EyesWidget w) { + xcb_generic_event_t *ev; + + if (!w->eyes.present) + return; + + if (!w->eyes.back_buffer) { + xcb_create_pixmap(xt_xcb(w), + w->core.depth, + w->eyes.back_buffer = xcb_generate_id(xt_xcb(w)), + XtWindow(w), + w->core.width, + w->core.height); + } + if (!w->eyes.back_damage) { + xcb_damage_create(xt_xcb(w), + w->eyes.back_damage = xcb_generate_id(xt_xcb(w)), + w->eyes.back_buffer, + XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); + xcb_xfixes_create_region(xt_xcb(w), + w->eyes.back_region = xcb_generate_id(xt_xcb(w)), + 0, NULL); + } +} + +static void UpdatePresent(EyesWidget w) { + if (w->eyes.back_buffer) { + xcb_damage_subtract(xt_xcb(w), + w->eyes.back_damage, + None, + w->eyes.back_region); + xcb_present_pixmap(xt_xcb(w), + XtWindow(w), + w->eyes.back_buffer, + 0, + None, + w->eyes.back_region, + 0, 0, + None, + None, + None, + 0, + 0, 1, 0, + 0, NULL); + } +} + +#endif + +#ifdef PRESENT +#define EyesDrawable(w) (w->eyes.back_buffer ? w->eyes.back_buffer : XtWindow(w)) +#else +#define EyesDrawable(w) XtWindow(w) +#endif + +static void draw_it_core(EyesWidget w); + +static void EyesGeneric(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch) +{ + draw_it_core((EyesWidget) w); +} + /* ARGSUSED */ static void Initialize ( Widget greq, @@ -197,6 +327,11 @@ static void Initialize ( w->eyes.fill[i] = XRenderCreateSolidFill(XtDisplay (w), &rc); } #endif +#ifdef PRESENT + w->eyes.back_buffer = None; + w->eyes.back_damage = None; + CheckPresent(w); +#endif } static void @@ -213,7 +348,7 @@ drawEllipse(EyesWidget w, enum EyesPart part, Trectangle(&w->eyes.t, &tpos, &pos); if (part == PART_CLEAR) { - XFillRectangle(XtDisplay(w), XtWindow(w), + XFillRectangle(XtDisplay(w), EyesDrawable(w), w->eyes.gc[PART_CENTER], (int)pos.x, (int)pos.y, (int)pos.width+2, (int)pos.height+2); @@ -275,7 +410,7 @@ drawEllipse(EyesWidget w, enum EyesPart part, TPOINT_NONE, TPOINT_NONE, diam); XFillArc(XtDisplay(w), - part == PART_SHAPE ? w->eyes.shape_mask : XtWindow(w), + part == PART_SHAPE ? w->eyes.shape_mask : EyesDrawable(w), w->eyes.gc[part], (int)(pos.x + 0.5), (int)(pos.y + 0.5), (int)(pos.width + 0.0), (int)(pos.height + 0.0), @@ -406,11 +541,17 @@ eyeBall(EyesWidget w, static void repaint_window (EyesWidget w) { if (XtIsRealized ((Widget) w)) { +#ifdef PRESENT + MakePresentData(w); +#endif eyeLiner (w, TRUE, 0); eyeLiner (w, TRUE, 1); computePupils (w, w->eyes.mouse, w->eyes.pupil); eyeBall (w, TRUE, NULL, 0); eyeBall (w, TRUE, NULL, 1); +#ifdef PRESENT + UpdatePresent(w); +#endif } } @@ -440,6 +581,9 @@ drawEyes(EyesWidget w, TPoint mouse) TPoint newpupil[2]; int num; +#ifdef PRESENT + MakePresentData(w); +#endif if (TPointEqual (mouse, w->eyes.mouse)) { if (delays[w->eyes.update + 1] != 0) ++w->eyes.update; @@ -452,6 +596,9 @@ drawEyes(EyesWidget w, TPoint mouse) w->eyes.mouse = mouse; w->eyes.update = 0; +#ifdef PRESENT + UpdatePresent(w); +#endif } static void draw_it_core(EyesWidget w) @@ -497,12 +644,25 @@ static void Resize (Widget gw) if (XtIsRealized (gw)) { - XClearWindow (dpy, XtWindow (w)); SetTransform (&w->eyes.t, 0, w->core.width, w->core.height, 0, W_MIN_X, W_MAX_X, W_MIN_Y, W_MAX_Y); +#ifdef PRESENT + if (w->eyes.back_buffer) { + xcb_free_pixmap(xt_xcb(w), + w->eyes.back_buffer); + w->eyes.back_buffer = None; + xcb_damage_destroy(xt_xcb(w), + w->eyes.back_damage); + w->eyes.back_damage = None; + } + MakePresentData(w); +#endif + if (EyesDrawable(w) == XtWindow(w)) + XClearWindow (dpy, XtWindow (w)); + #ifdef XRENDER if (w->eyes.picture) { XRenderFreePicture(dpy, w->eyes.picture); @@ -537,7 +697,7 @@ static void Resize (Widget gw) pf = XRenderFindVisualFormat(dpy, DefaultVisualOfScreen(w->core.screen)); if (pf) - w->eyes.picture = XRenderCreatePicture(dpy, XtWindow (w), + w->eyes.picture = XRenderCreatePicture(dpy, EyesDrawable (w), pf, 0, &pa); } #endif @@ -35,6 +35,8 @@ #define XtNrender "render" #define XtNdistance "distance" +#define XtNpresent "present" + enum EyesPart { PART_CLEAR = -1, @@ -8,6 +8,13 @@ #include <X11/extensions/Xrender.h> #endif #include "transform.h" +#ifdef PRESENT +#include <X11/Xlib-xcb.h> +#include <xcb/xcb.h> +#include <xcb/present.h> +#include <xcb/xfixes.h> +#include <xcb/damage.h> +#endif #define SEG_BUFF_SIZE 128 @@ -31,9 +38,17 @@ typedef struct { Picture picture; Picture fill[PART_SHAPE]; #endif +#ifdef PRESENT + Pixmap back_buffer; + xcb_damage_damage_t back_damage; + xcb_xfixes_region_t back_region; + Boolean present; +#endif Boolean distance; } EyesPart; +#define xt_xcb(w) (XGetXCBConnection(XtDisplay(w))) + /* Full instance record declaration */ typedef struct _EyesRec { CorePart core; diff --git a/Makefile.am b/Makefile.am index 9889544..fe14b6d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,8 +22,8 @@ SUBDIRS = man bin_PROGRAMS = xeyes -AM_CFLAGS = $(XEYES_CFLAGS) $(XRENDER_CFLAGS) $(CWARNFLAGS) -xeyes_LDADD = $(XEYES_LIBS) $(XRENDER_LIBS) -lm +AM_CFLAGS = $(XEYES_CFLAGS) $(XRENDER_CFLAGS) $(PRESENT_CFLAGS) $(CWARNFLAGS) +xeyes_LDADD = $(XEYES_LIBS) $(XRENDER_LIBS) $(PRESENT_LIBS) -lm xeyes_SOURCES = \ Eyes.c \ diff --git a/configure.ac b/configure.ac index 031692e..3171978 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,12 @@ if test x$use_xrender != xno ; then AC_DEFINE([XRENDER],1,[Define to use X Render Extension]) fi +AC_ARG_WITH(present, AS_HELP_STRING([--with-present],[Use Present for updates (Default is AUTO)]),use_present="$withval",use_present="try") +if test x$use_present != xno ; then + PKG_CHECK_MODULES(PRESENT, [x11-xcb xcb-present >= 1.9 xcb-xfixes xcb-damage]) + AC_DEFINE([PRESENT],1,[Define to use X Present Extension]) +fi + AC_CONFIG_FILES([ Makefile man/Makefile]) @@ -57,6 +57,10 @@ usage(void) fprintf(stderr, " [-render | +render]\n"); #endif +#ifdef PRESENT + fprintf(stderr, + " [-present | +present]\n"); +#endif exit(1); } @@ -73,6 +77,10 @@ static XrmOptionDescRec options[] = { {"-render", "*eyes.render", XrmoptionNoArg, "TRUE"}, {"+render", "*eyes.render", XrmoptionNoArg, "FALSE"}, #endif +#ifdef PRESENT +{"-present", "*eyes.present", XrmoptionNoArg, "TRUE"}, +{"+present", "*eyes.present", XrmoptionNoArg, "FALSE"}, +#endif {"-distance", "*eyes.distance", XrmoptionNoArg, "TRUE"}, }; |