Eyes.c revision 26df5c7c
1a1d141d5Smrg/* 2a1d141d5Smrg 3a1d141d5SmrgCopyright (c) 1991 X Consortium 4a1d141d5Smrg 5a1d141d5SmrgPermission is hereby granted, free of charge, to any person obtaining 6a1d141d5Smrga copy of this software and associated documentation files (the 7a1d141d5Smrg"Software"), to deal in the Software without restriction, including 8a1d141d5Smrgwithout limitation the rights to use, copy, modify, merge, publish, 9a1d141d5Smrgdistribute, sublicense, and/or sell copies of the Software, and to 10a1d141d5Smrgpermit persons to whom the Software is furnished to do so, subject to 11a1d141d5Smrgthe following conditions: 12a1d141d5Smrg 13a1d141d5SmrgThe above copyright notice and this permission notice shall be included 14a1d141d5Smrgin all copies or substantial portions of the Software. 15a1d141d5Smrg 16a1d141d5SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17a1d141d5SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18a1d141d5SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19a1d141d5SmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 20a1d141d5SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21a1d141d5SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22a1d141d5SmrgOTHER DEALINGS IN THE SOFTWARE. 23a1d141d5Smrg 24a1d141d5SmrgExcept as contained in this notice, the name of the X Consortium shall 25a1d141d5Smrgnot be used in advertising or otherwise to promote the sale, use or 26a1d141d5Smrgother dealings in this Software without prior written authorization 27a1d141d5Smrgfrom the X Consortium. 28a1d141d5Smrg 29a1d141d5Smrg*/ 30a1d141d5Smrg 31a1d141d5Smrg/* 32a1d141d5Smrg * Eyes.c 33a1d141d5Smrg * 34a1d141d5Smrg * a widget which follows the mouse around 35a1d141d5Smrg */ 36a1d141d5Smrg 372ddb6cf1Smrg#ifdef HAVE_CONFIG_H 382ddb6cf1Smrg# include "config.h" 392ddb6cf1Smrg#endif 402ddb6cf1Smrg 41a1d141d5Smrg# include <X11/Xos.h> 42a1d141d5Smrg# include <stdio.h> 43a1d141d5Smrg# include <X11/IntrinsicP.h> 44a1d141d5Smrg# include <X11/StringDefs.h> 45a1d141d5Smrg# include <X11/Xmu/Converters.h> 46a1d141d5Smrg# include "EyesP.h" 47a1d141d5Smrg# include <math.h> 48a1d141d5Smrg# include <X11/extensions/shape.h> 492ddb6cf1Smrg# include <X11/Xlibint.h> 502ddb6cf1Smrg# include <stdlib.h> 5126df5c7cSmrg# include <X11/extensions/XInput2.h> 52a1d141d5Smrg 53a1d141d5Smrg#define offset(field) XtOffsetOf(EyesRec, eyes.field) 54a1d141d5Smrg#define goffset(field) XtOffsetOf(WidgetRec, core.field) 55a1d141d5Smrg 56a1d141d5Smrgstatic XtResource resources[] = { 5726df5c7cSmrg {(char *) XtNwidth, (char *) XtCWidth, XtRDimension, sizeof(Dimension), 58a1d141d5Smrg goffset(width), XtRImmediate, (XtPointer) 150}, 5926df5c7cSmrg {(char *) XtNheight, (char *) XtCHeight, XtRDimension, sizeof(Dimension), 60a1d141d5Smrg goffset(height), XtRImmediate, (XtPointer) 100}, 6126df5c7cSmrg {(char *) XtNforeground, (char *) XtCForeground, XtRPixel, sizeof(Pixel), 6226df5c7cSmrg offset(pixel[PART_PUPIL]), XtRString, (char *) XtDefaultForeground}, 6326df5c7cSmrg {(char *) XtNbackgroundPixmap, (char *) XtCPixmap, XtRPixmap, sizeof(Pixmap), 6426df5c7cSmrg XtOffsetOf(CoreRec,core.background_pixmap), 6526df5c7cSmrg XtRImmediate, (XtPointer)None}, 6626df5c7cSmrg {(char *) XtNoutline, (char *) XtCForeground, XtRPixel, sizeof(Pixel), 6726df5c7cSmrg offset(pixel[PART_OUTLINE]), XtRString, (char *) XtDefaultForeground}, 6826df5c7cSmrg {(char *) XtNcenterColor, (char *) XtCBackground, XtRPixel, sizeof (Pixel), 6926df5c7cSmrg offset(pixel[PART_CENTER]), XtRString, (char *) XtDefaultBackground}, 7026df5c7cSmrg {(char *) XtNreverseVideo, (char *) XtCReverseVideo, XtRBoolean, sizeof (Boolean), 71a1d141d5Smrg offset (reverse_video), XtRImmediate, (XtPointer) FALSE}, 7226df5c7cSmrg {(char *) XtNbackingStore, (char *) XtCBackingStore, (char *) XtRBackingStore, sizeof (int), 7326df5c7cSmrg offset (backing_store), XtRString, (char *) "default"}, 7426df5c7cSmrg {(char *) XtNshapeWindow, (char *) XtCShapeWindow, XtRBoolean, sizeof (Boolean), 75a1d141d5Smrg offset (shape_window), XtRImmediate, (XtPointer) TRUE}, 762ddb6cf1Smrg#ifdef XRENDER 7726df5c7cSmrg {(char *) XtNrender, (char *) XtCBoolean, XtRBoolean, sizeof(Boolean), 782ddb6cf1Smrg offset(render), XtRImmediate, (XtPointer) TRUE }, 792ddb6cf1Smrg#endif 8026df5c7cSmrg#ifdef PRESENT 8126df5c7cSmrg {(char *) XtNpresent, (char *) XtCBoolean, XtRBoolean, sizeof(Boolean), 8226df5c7cSmrg offset(present), XtRImmediate, (XtPointer) TRUE }, 8326df5c7cSmrg#endif 8426df5c7cSmrg {(char *) XtNdistance, (char *) XtCBoolean, XtRBoolean, sizeof(Boolean), 852ddb6cf1Smrg offset(distance), XtRImmediate, (XtPointer) FALSE }, 86a1d141d5Smrg}; 87a1d141d5Smrg 88a1d141d5Smrg#undef offset 89a1d141d5Smrg#undef goffset 90a1d141d5Smrg 91a1d141d5Smrg# define EYE_X(n) ((n) * 2.0) 92a1d141d5Smrg# define EYE_Y(n) (0.0) 93a1d141d5Smrg# define EYE_OFFSET (0.1) /* padding between eyes */ 94a1d141d5Smrg# define EYE_THICK (0.175) /* thickness of eye rim */ 952ddb6cf1Smrg# define BALL_DIAM (0.3) 962ddb6cf1Smrg# define BALL_PAD (0.175) 972ddb6cf1Smrg# define EYE_DIAM (2.0 - (EYE_THICK + EYE_OFFSET) * 2) 982ddb6cf1Smrg# define BALL_DIST ((EYE_DIAM - BALL_DIAM) / 2.0 - BALL_PAD) 99a1d141d5Smrg# define W_MIN_X (-1.0 + EYE_OFFSET) 100a1d141d5Smrg# define W_MAX_X (3.0 - EYE_OFFSET) 101a1d141d5Smrg# define W_MIN_Y (-1.0 + EYE_OFFSET) 102a1d141d5Smrg# define W_MAX_Y (1.0 - EYE_OFFSET) 103a1d141d5Smrg 1042ddb6cf1Smrg# define TPOINT_NONE (-1000) /* special value meaning "not yet set" */ 105a1d141d5Smrg# define TPointEqual(a, b) ((a).x == (b).x && (a).y == (b).y) 106a1d141d5Smrg# define XPointEqual(a, b) ((a).x == (b).x && (a).y == (b).y) 1072ddb6cf1Smrg# define AngleBetween(A, A0, A1) (A0 <= A1 ? A0 <= A && A <= A1 : \ 1082ddb6cf1Smrg A0 <= A || A <= A1) 109a1d141d5Smrg 110a1d141d5Smrgstatic int delays[] = { 50, 100, 200, 400, 0 }; 111a1d141d5Smrg 112a1d141d5Smrgstatic void ClassInitialize(void) 113a1d141d5Smrg{ 114a1d141d5Smrg XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, 115a1d141d5Smrg NULL, 0 ); 116a1d141d5Smrg} 117a1d141d5Smrg 118a1d141d5SmrgWidgetClass eyesWidgetClass = (WidgetClass) &eyesClassRec; 119a1d141d5Smrg 12026df5c7cSmrg#ifdef PRESENT 12126df5c7cSmrgstatic void CheckPresent(EyesWidget w) { 12226df5c7cSmrg const xcb_query_extension_reply_t *xfixes_ext_reply; 12326df5c7cSmrg const xcb_query_extension_reply_t *damage_ext_reply; 12426df5c7cSmrg const xcb_query_extension_reply_t *present_ext_reply; 12526df5c7cSmrg xcb_xfixes_query_version_cookie_t xfixes_cookie; 12626df5c7cSmrg xcb_xfixes_query_version_reply_t *xfixes_reply; 12726df5c7cSmrg xcb_damage_query_version_cookie_t damage_cookie; 12826df5c7cSmrg xcb_damage_query_version_reply_t *damage_reply; 12926df5c7cSmrg xcb_present_query_version_cookie_t present_cookie; 13026df5c7cSmrg xcb_present_query_version_reply_t *present_reply; 13126df5c7cSmrg 13226df5c7cSmrg if (!w->eyes.present) 13326df5c7cSmrg return; 13426df5c7cSmrg 13526df5c7cSmrg xcb_prefetch_extension_data(xt_xcb(w), &xcb_xfixes_id); 13626df5c7cSmrg xcb_prefetch_extension_data(xt_xcb(w), &xcb_damage_id); 13726df5c7cSmrg xcb_prefetch_extension_data(xt_xcb(w), &xcb_present_id); 13826df5c7cSmrg 13926df5c7cSmrg xfixes_ext_reply = xcb_get_extension_data(xt_xcb(w), &xcb_xfixes_id); 14026df5c7cSmrg damage_ext_reply = xcb_get_extension_data(xt_xcb(w), &xcb_damage_id); 14126df5c7cSmrg present_ext_reply = xcb_get_extension_data(xt_xcb(w), &xcb_present_id); 14226df5c7cSmrg if (xfixes_ext_reply == NULL || !xfixes_ext_reply->present 14326df5c7cSmrg || damage_ext_reply == NULL || !damage_ext_reply->present 14426df5c7cSmrg || present_ext_reply == NULL || !present_ext_reply->present) 14526df5c7cSmrg { 14626df5c7cSmrg w->eyes.present = FALSE; 14726df5c7cSmrg } 14826df5c7cSmrg 14926df5c7cSmrg if (!w->eyes.present) 15026df5c7cSmrg return; 15126df5c7cSmrg 15226df5c7cSmrg /* Now tell the server which versions of the extensions we support */ 15326df5c7cSmrg xfixes_cookie = xcb_xfixes_query_version(xt_xcb(w), 15426df5c7cSmrg XCB_XFIXES_MAJOR_VERSION, 15526df5c7cSmrg XCB_XFIXES_MINOR_VERSION); 15626df5c7cSmrg 15726df5c7cSmrg damage_cookie = xcb_damage_query_version(xt_xcb(w), 15826df5c7cSmrg XCB_DAMAGE_MAJOR_VERSION, 15926df5c7cSmrg XCB_DAMAGE_MINOR_VERSION); 16026df5c7cSmrg 16126df5c7cSmrg present_cookie = xcb_present_query_version(xt_xcb(w), 16226df5c7cSmrg XCB_PRESENT_MAJOR_VERSION, 16326df5c7cSmrg XCB_PRESENT_MINOR_VERSION); 16426df5c7cSmrg 16526df5c7cSmrg xfixes_reply = xcb_xfixes_query_version_reply(xt_xcb(w), 16626df5c7cSmrg xfixes_cookie, 16726df5c7cSmrg NULL); 16826df5c7cSmrg free(xfixes_reply); 16926df5c7cSmrg 17026df5c7cSmrg damage_reply = xcb_damage_query_version_reply(xt_xcb(w), 17126df5c7cSmrg damage_cookie, 17226df5c7cSmrg NULL); 17326df5c7cSmrg free(damage_reply); 17426df5c7cSmrg 17526df5c7cSmrg present_reply = xcb_present_query_version_reply(xt_xcb(w), 17626df5c7cSmrg present_cookie, 17726df5c7cSmrg NULL); 17826df5c7cSmrg free(present_reply); 17926df5c7cSmrg} 18026df5c7cSmrg 18126df5c7cSmrgstatic void MakePresentData(EyesWidget w) { 18226df5c7cSmrg 18326df5c7cSmrg if (!w->eyes.present) 18426df5c7cSmrg return; 18526df5c7cSmrg 18626df5c7cSmrg if (!w->eyes.back_buffer) { 18726df5c7cSmrg xcb_create_pixmap(xt_xcb(w), 18826df5c7cSmrg w->core.depth, 18926df5c7cSmrg w->eyes.back_buffer = xcb_generate_id(xt_xcb(w)), 19026df5c7cSmrg XtWindow(w), 19126df5c7cSmrg w->core.width, 19226df5c7cSmrg w->core.height); 19326df5c7cSmrg } 19426df5c7cSmrg if (!w->eyes.back_damage) { 19526df5c7cSmrg xcb_damage_create(xt_xcb(w), 19626df5c7cSmrg w->eyes.back_damage = xcb_generate_id(xt_xcb(w)), 19726df5c7cSmrg w->eyes.back_buffer, 19826df5c7cSmrg XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); 19926df5c7cSmrg xcb_xfixes_create_region(xt_xcb(w), 20026df5c7cSmrg w->eyes.back_region = xcb_generate_id(xt_xcb(w)), 20126df5c7cSmrg 0, NULL); 20226df5c7cSmrg } 20326df5c7cSmrg} 20426df5c7cSmrg 20526df5c7cSmrgstatic void UpdatePresent(EyesWidget w) { 20626df5c7cSmrg if (w->eyes.back_buffer) { 20726df5c7cSmrg xcb_damage_subtract(xt_xcb(w), 20826df5c7cSmrg w->eyes.back_damage, 20926df5c7cSmrg None, 21026df5c7cSmrg w->eyes.back_region); 21126df5c7cSmrg xcb_present_pixmap(xt_xcb(w), 21226df5c7cSmrg XtWindow(w), 21326df5c7cSmrg w->eyes.back_buffer, 21426df5c7cSmrg 0, 21526df5c7cSmrg None, 21626df5c7cSmrg w->eyes.back_region, 21726df5c7cSmrg 0, 0, 21826df5c7cSmrg None, 21926df5c7cSmrg None, 22026df5c7cSmrg None, 22126df5c7cSmrg 0, 22226df5c7cSmrg 0, 1, 0, 22326df5c7cSmrg 0, NULL); 22426df5c7cSmrg } 22526df5c7cSmrg} 22626df5c7cSmrg 22726df5c7cSmrg#endif 22826df5c7cSmrg 22926df5c7cSmrg#ifdef PRESENT 23026df5c7cSmrg#define EyesDrawable(w) (w->eyes.back_buffer ? w->eyes.back_buffer : XtWindow(w)) 23126df5c7cSmrg#else 23226df5c7cSmrg#define EyesDrawable(w) XtWindow(w) 23326df5c7cSmrg#endif 23426df5c7cSmrg 23526df5c7cSmrgstatic void draw_it_core(EyesWidget w); 23626df5c7cSmrg 23726df5c7cSmrgstatic void EyesGeneric(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch) 23826df5c7cSmrg{ 23926df5c7cSmrg draw_it_core((EyesWidget) w); 24026df5c7cSmrg} 24126df5c7cSmrg 24226df5c7cSmrgstruct root_listen_list { 24326df5c7cSmrg struct root_listen_list *next; 24426df5c7cSmrg Widget widget; 24526df5c7cSmrg}; 24626df5c7cSmrg 24726df5c7cSmrgstatic struct root_listen_list *root_listen_list; 24826df5c7cSmrg 24926df5c7cSmrgstatic Boolean xi2_dispatcher(XEvent *event) { 25026df5c7cSmrg struct root_listen_list *rll; 25126df5c7cSmrg Boolean was_dispatched = False; 25226df5c7cSmrg 25326df5c7cSmrg for (rll = root_listen_list; rll; rll = rll->next) { 25426df5c7cSmrg if (XtDisplay(rll->widget) == event->xany.display) { 25526df5c7cSmrg XtDispatchEventToWidget(rll->widget, event); 25626df5c7cSmrg was_dispatched = True; 25726df5c7cSmrg } 25826df5c7cSmrg } 25926df5c7cSmrg return was_dispatched; 26026df5c7cSmrg} 26126df5c7cSmrg 26226df5c7cSmrgstatic void select_xi2_events(Widget w) 26326df5c7cSmrg{ 26426df5c7cSmrg XIEventMask evmasks[1]; 26526df5c7cSmrg unsigned char mask1[(XI_LASTEVENT + 7)/8]; 26626df5c7cSmrg 26726df5c7cSmrg memset(mask1, 0, sizeof(mask1)); 26826df5c7cSmrg 26926df5c7cSmrg /* select for button and key events from all master devices */ 27026df5c7cSmrg XISetMask(mask1, XI_RawMotion); 27126df5c7cSmrg 27226df5c7cSmrg evmasks[0].deviceid = XIAllMasterDevices; 27326df5c7cSmrg evmasks[0].mask_len = sizeof(mask1); 27426df5c7cSmrg evmasks[0].mask = mask1; 27526df5c7cSmrg 27626df5c7cSmrg XISelectEvents(XtDisplay(w), 27726df5c7cSmrg RootWindowOfScreen(XtScreen(w)), 27826df5c7cSmrg evmasks, 1); 27926df5c7cSmrg XtSetEventDispatcher(XtDisplay(w), 28026df5c7cSmrg GenericEvent, 28126df5c7cSmrg xi2_dispatcher); 28226df5c7cSmrg} 28326df5c7cSmrg 28426df5c7cSmrgstatic Boolean xi2_add_root_listener(Widget widget) 28526df5c7cSmrg{ 28626df5c7cSmrg struct root_listen_list *rll = malloc (sizeof (struct root_listen_list)); 28726df5c7cSmrg 28826df5c7cSmrg if (!rll) 28926df5c7cSmrg return False; 29026df5c7cSmrg rll->widget = widget; 29126df5c7cSmrg rll->next = root_listen_list; 29226df5c7cSmrg if (!root_listen_list) 29326df5c7cSmrg select_xi2_events(widget); 29426df5c7cSmrg root_listen_list = rll; 29526df5c7cSmrg XtInsertEventTypeHandler(widget, GenericEvent, NULL, EyesGeneric, NULL, XtListHead); 29626df5c7cSmrg return True; 29726df5c7cSmrg} 29826df5c7cSmrg 29926df5c7cSmrgstatic void xi2_remove_root_listener(Widget widget) 30026df5c7cSmrg{ 30126df5c7cSmrg struct root_listen_list *rll, **prev; 30226df5c7cSmrg 30326df5c7cSmrg for (prev = &root_listen_list; (rll = *prev) != NULL; prev = &rll->next) { 30426df5c7cSmrg if (rll->widget == widget) { 30526df5c7cSmrg *prev = rll->next; 30626df5c7cSmrg free(rll); 30726df5c7cSmrg break; 30826df5c7cSmrg } 30926df5c7cSmrg } 31026df5c7cSmrg} 31126df5c7cSmrg 31226df5c7cSmrg/* Return 1 if XI2 is available, 0 otherwise */ 31326df5c7cSmrgstatic int has_xi2(Display *dpy) 31426df5c7cSmrg{ 31526df5c7cSmrg int major, minor; 31626df5c7cSmrg int rc; 31726df5c7cSmrg 31826df5c7cSmrg /* We need at least XI 2.0 */ 31926df5c7cSmrg major = 2; 32026df5c7cSmrg minor = 0; 32126df5c7cSmrg 32226df5c7cSmrg rc = XIQueryVersion(dpy, &major, &minor); 32326df5c7cSmrg if (rc == BadRequest) { 32426df5c7cSmrg return 0; 32526df5c7cSmrg } else if (rc != Success) { 32626df5c7cSmrg return 0; 32726df5c7cSmrg } 32826df5c7cSmrg return 1; 32926df5c7cSmrg} 33026df5c7cSmrg 33126df5c7cSmrg 332a1d141d5Smrg/* ARGSUSED */ 333a1d141d5Smrgstatic void Initialize ( 334a1d141d5Smrg Widget greq, 335a1d141d5Smrg Widget gnew, 336a1d141d5Smrg ArgList args, 337a1d141d5Smrg Cardinal *num_args) 338a1d141d5Smrg{ 339a1d141d5Smrg EyesWidget w = (EyesWidget)gnew; 340a1d141d5Smrg XtGCMask valuemask; 341a1d141d5Smrg XGCValues myXGCV; 342a1d141d5Smrg int shape_event_base, shape_error_base; 3432ddb6cf1Smrg#ifdef XRENDER 3442ddb6cf1Smrg enum EyesPart i; 3452ddb6cf1Smrg#endif 346a1d141d5Smrg 347a1d141d5Smrg /* 348a1d141d5Smrg * set the colors if reverse video; these are the colors used: 349a1d141d5Smrg * 350a1d141d5Smrg * background - paper white 351a1d141d5Smrg * foreground - text, ticks black 352a1d141d5Smrg * border - border black (foreground) 353a1d141d5Smrg * 3542ddb6cf1Smrg * This doesn't completely work since the parent has already made up a 355a1d141d5Smrg * border. Sigh. 356a1d141d5Smrg */ 357a1d141d5Smrg if (w->eyes.reverse_video) { 3582ddb6cf1Smrg Pixel fg = w->eyes.pixel[PART_PUPIL]; 359a1d141d5Smrg Pixel bg = w->core.background_pixel; 360a1d141d5Smrg 361a1d141d5Smrg if (w->core.border_pixel == fg) 362a1d141d5Smrg w->core.border_pixel = bg; 3632ddb6cf1Smrg if (w->eyes.pixel[PART_OUTLINE] == fg) 3642ddb6cf1Smrg w->eyes.pixel[PART_OUTLINE] = bg; 3652ddb6cf1Smrg if (w->eyes.pixel[PART_CENTER] == bg) 3662ddb6cf1Smrg w->eyes.pixel[PART_CENTER] = fg; 3672ddb6cf1Smrg w->eyes.pixel[PART_PUPIL] = bg; 368a1d141d5Smrg w->core.background_pixel = fg; 369a1d141d5Smrg } 370a1d141d5Smrg 3712ddb6cf1Smrg myXGCV.foreground = w->eyes.pixel[PART_PUPIL]; 372a1d141d5Smrg myXGCV.background = w->core.background_pixel; 373a1d141d5Smrg valuemask = GCForeground | GCBackground; 3742ddb6cf1Smrg w->eyes.gc[PART_PUPIL] = XtGetGC(gnew, valuemask, &myXGCV); 375a1d141d5Smrg 3762ddb6cf1Smrg myXGCV.foreground = w->eyes.pixel[PART_OUTLINE]; 377a1d141d5Smrg valuemask = GCForeground | GCBackground; 3782ddb6cf1Smrg w->eyes.gc[PART_OUTLINE] = XtGetGC(gnew, valuemask, &myXGCV); 379a1d141d5Smrg 3802ddb6cf1Smrg myXGCV.foreground = w->eyes.pixel[PART_CENTER]; 3812ddb6cf1Smrg myXGCV.background = w->eyes.pixel[PART_PUPIL]; 382a1d141d5Smrg valuemask = GCForeground | GCBackground; 3832ddb6cf1Smrg w->eyes.gc[PART_CENTER] = XtGetGC(gnew, valuemask, &myXGCV); 384a1d141d5Smrg 385a1d141d5Smrg w->eyes.update = 0; 386a1d141d5Smrg /* wait for Realize to add the timeout */ 387a1d141d5Smrg w->eyes.interval_id = 0; 388a1d141d5Smrg 3892ddb6cf1Smrg w->eyes.pupil[0].x = w->eyes.pupil[1].x = TPOINT_NONE; 3902ddb6cf1Smrg w->eyes.pupil[0].y = w->eyes.pupil[1].y = TPOINT_NONE; 391a1d141d5Smrg 3922ddb6cf1Smrg w->eyes.mouse.x = w->eyes.mouse.y = TPOINT_NONE; 393a1d141d5Smrg 394a1d141d5Smrg if (w->eyes.shape_window && !XShapeQueryExtension (XtDisplay (w), 395a1d141d5Smrg &shape_event_base, 396a1d141d5Smrg &shape_error_base)) 397a1d141d5Smrg w->eyes.shape_window = False; 398a1d141d5Smrg w->eyes.shape_mask = 0; 3992ddb6cf1Smrg w->eyes.gc[PART_SHAPE] = NULL; 4002ddb6cf1Smrg 40126df5c7cSmrg w->eyes.has_xi2 = has_xi2(XtDisplay(w)); 40226df5c7cSmrg 4032ddb6cf1Smrg#ifdef XRENDER 4042ddb6cf1Smrg for (i = 0; i < PART_SHAPE; i ++) { 4052ddb6cf1Smrg XColor c; 4062ddb6cf1Smrg XRenderColor rc; 4072ddb6cf1Smrg 4082ddb6cf1Smrg c.pixel = w->eyes.pixel[i]; 4092ddb6cf1Smrg XQueryColor(XtDisplay (w), w->core.colormap, &c); 4102ddb6cf1Smrg 4112ddb6cf1Smrg rc.red = c.red; 4122ddb6cf1Smrg rc.green = c.green; 4132ddb6cf1Smrg rc.blue = c.blue; 4142ddb6cf1Smrg rc.alpha = -1; 4152ddb6cf1Smrg w->eyes.fill[i] = XRenderCreateSolidFill(XtDisplay (w), &rc); 4162ddb6cf1Smrg } 4172ddb6cf1Smrg#endif 41826df5c7cSmrg#ifdef PRESENT 41926df5c7cSmrg w->eyes.back_buffer = None; 42026df5c7cSmrg w->eyes.back_damage = None; 42126df5c7cSmrg CheckPresent(w); 42226df5c7cSmrg#endif 423a1d141d5Smrg} 424a1d141d5Smrg 4252ddb6cf1Smrgstatic void 4262ddb6cf1SmrgdrawEllipse(EyesWidget w, enum EyesPart part, 4272ddb6cf1Smrg double centerx, double centery, 4282ddb6cf1Smrg double oldx, double oldy, 4292ddb6cf1Smrg double diam) 430a1d141d5Smrg{ 4312ddb6cf1Smrg const TRectangle tpos = { 4322ddb6cf1Smrg centerx - diam/2.0, 4332ddb6cf1Smrg centery - diam/2.0, 4342ddb6cf1Smrg diam, diam }; 4352ddb6cf1Smrg TRectangle pos; 4362ddb6cf1Smrg Trectangle(&w->eyes.t, &tpos, &pos); 4372ddb6cf1Smrg 4382ddb6cf1Smrg if (part == PART_CLEAR) { 43926df5c7cSmrg XFillRectangle(XtDisplay(w), EyesDrawable(w), 4402ddb6cf1Smrg w->eyes.gc[PART_CENTER], 4412ddb6cf1Smrg (int)pos.x, (int)pos.y, 4422ddb6cf1Smrg (int)pos.width+2, (int)pos.height+2); 4432ddb6cf1Smrg return; 4442ddb6cf1Smrg } 4452ddb6cf1Smrg#ifdef XRENDER 4462ddb6cf1Smrg if (w->eyes.render && part != PART_SHAPE && (!w->eyes.shape_window || 4472ddb6cf1Smrg part != PART_OUTLINE) && 4482ddb6cf1Smrg w->eyes.picture) { 4492ddb6cf1Smrg int n, i; 4502ddb6cf1Smrg double hd, c, s, sx, sy, x, y, px, py; 4512ddb6cf1Smrg XPointDouble *p; 4522ddb6cf1Smrg 4532ddb6cf1Smrg pos.x = pos.x + pos.width/2.0; 4542ddb6cf1Smrg pos.y = pos.y + pos.height/2.0; 4552ddb6cf1Smrg 4562ddb6cf1Smrg /* determine number of segments to draw */ 4572ddb6cf1Smrg hd = hypot(pos.width, pos.height)/2; 4582ddb6cf1Smrg n = (M_PI / acos(hd/(hd+1.0))) + 0.5; 4592ddb6cf1Smrg if (n < 2) n = 2; 4602ddb6cf1Smrg 4612ddb6cf1Smrg c = cos(M_PI/n); 4622ddb6cf1Smrg s = sin(M_PI/n); 4632ddb6cf1Smrg sx = -(pos.width*s)/pos.height; 4642ddb6cf1Smrg sy = (pos.height*s)/pos.width; 4652ddb6cf1Smrg 4662ddb6cf1Smrg n *= 2; 4672ddb6cf1Smrg p = Xmalloc(sizeof(*p)*n); 4682ddb6cf1Smrg if (!p) 4692ddb6cf1Smrg return; 4702ddb6cf1Smrg x = 0; 4712ddb6cf1Smrg y = pos.height/2.0; 4722ddb6cf1Smrg for (i = 0; i < n; i ++) 4732ddb6cf1Smrg { 4742ddb6cf1Smrg p[i].x = x + pos.x; 4752ddb6cf1Smrg p[i].y = y + pos.y; 4762ddb6cf1Smrg px = x; 4772ddb6cf1Smrg py = y; 4782ddb6cf1Smrg x = c*px + sx*py; 4792ddb6cf1Smrg y = c*py + sy*px; 480a1d141d5Smrg } 4812ddb6cf1Smrg 4822ddb6cf1Smrg if (oldx != TPOINT_NONE || oldy != TPOINT_NONE) 4832ddb6cf1Smrg drawEllipse(w, PART_CLEAR, oldx, oldy, 4842ddb6cf1Smrg TPOINT_NONE, TPOINT_NONE, diam); 4852ddb6cf1Smrg 4862ddb6cf1Smrg XRenderCompositeDoublePoly(XtDisplay(w), PictOpOver, 4872ddb6cf1Smrg w->eyes.fill[part], w->eyes.picture, 4882ddb6cf1Smrg XRenderFindStandardFormat(XtDisplay(w), 4892ddb6cf1Smrg PictStandardA8), 4902ddb6cf1Smrg 0, 0, 0, 0, p, n, 0); 4912ddb6cf1Smrg 4922ddb6cf1Smrg Xfree(p); 4932ddb6cf1Smrg return; 4942ddb6cf1Smrg } 4952ddb6cf1Smrg#endif 4962ddb6cf1Smrg if (oldx != TPOINT_NONE || oldy != TPOINT_NONE) 4972ddb6cf1Smrg drawEllipse(w, PART_CLEAR, oldx, oldy, 4982ddb6cf1Smrg TPOINT_NONE, TPOINT_NONE, diam); 4992ddb6cf1Smrg 5002ddb6cf1Smrg XFillArc(XtDisplay(w), 50126df5c7cSmrg part == PART_SHAPE ? w->eyes.shape_mask : EyesDrawable(w), 5022ddb6cf1Smrg w->eyes.gc[part], 5032ddb6cf1Smrg (int)(pos.x + 0.5), (int)(pos.y + 0.5), 5042ddb6cf1Smrg (int)(pos.width + 0.0), (int)(pos.height + 0.0), 5052ddb6cf1Smrg 90*64, 360*64); 5062ddb6cf1Smrg} 5072ddb6cf1Smrg 5082ddb6cf1Smrg 5092ddb6cf1Smrgstatic void 5102ddb6cf1SmrgeyeLiner(EyesWidget w, 5112ddb6cf1Smrg Boolean draw, 5122ddb6cf1Smrg int num) 5132ddb6cf1Smrg{ 5142ddb6cf1Smrg drawEllipse(w, draw ? PART_OUTLINE : PART_SHAPE, 5152ddb6cf1Smrg EYE_X(num), EYE_Y(num), 5162ddb6cf1Smrg TPOINT_NONE, TPOINT_NONE, 5172ddb6cf1Smrg EYE_DIAM + 2.0*EYE_THICK); 5182ddb6cf1Smrg if (draw) { 5192ddb6cf1Smrg drawEllipse(w, PART_CENTER, EYE_X(num), EYE_Y(num), 5202ddb6cf1Smrg TPOINT_NONE, TPOINT_NONE, 5212ddb6cf1Smrg EYE_DIAM); 5222ddb6cf1Smrg } 523a1d141d5Smrg} 524a1d141d5Smrg 525a1d141d5Smrgstatic TPoint computePupil ( 526a1d141d5Smrg int num, 5272ddb6cf1Smrg TPoint mouse, 5282ddb6cf1Smrg const TRectangle *screen) 529a1d141d5Smrg{ 530a1d141d5Smrg double cx, cy; 531a1d141d5Smrg double dist; 532a1d141d5Smrg double angle; 533a1d141d5Smrg double dx, dy; 534a1d141d5Smrg double cosa, sina; 535a1d141d5Smrg TPoint ret; 536a1d141d5Smrg 5372ddb6cf1Smrg cx = EYE_X(num); dx = mouse.x - cx; 5382ddb6cf1Smrg cy = EYE_Y(num); dy = mouse.y - cy; 5392ddb6cf1Smrg if (dx == 0 && dy == 0); 5402ddb6cf1Smrg else { 541a1d141d5Smrg angle = atan2 ((double) dy, (double) dx); 542a1d141d5Smrg cosa = cos (angle); 543a1d141d5Smrg sina = sin (angle); 5442ddb6cf1Smrg dist = BALL_DIST; 5452ddb6cf1Smrg if (screen) 5462ddb6cf1Smrg { 5472ddb6cf1Smrg /* use distance mapping */ 5482ddb6cf1Smrg double x0, y0, x1, y1; 5492ddb6cf1Smrg double a[4]; 5502ddb6cf1Smrg x0 = screen->x - cx; 5512ddb6cf1Smrg y0 = screen->y - cy; 5522ddb6cf1Smrg x1 = x0 + screen->width; 5532ddb6cf1Smrg y1 = y0 + screen->height; 5542ddb6cf1Smrg a[0] = atan2(y0, x0); 5552ddb6cf1Smrg a[1] = atan2(y1, x0); 5562ddb6cf1Smrg a[2] = atan2(y1, x1); 5572ddb6cf1Smrg a[3] = atan2(y0, x1); 5582ddb6cf1Smrg if (AngleBetween(angle, a[0], a[1])) 5592ddb6cf1Smrg { 5602ddb6cf1Smrg /* left */ 5612ddb6cf1Smrg dist *= dx / x0; 5622ddb6cf1Smrg } 5632ddb6cf1Smrg else if (AngleBetween(angle, a[1], a[2])) 5642ddb6cf1Smrg { 5652ddb6cf1Smrg /* bottom */ 5662ddb6cf1Smrg dist *= dy / y1; 5672ddb6cf1Smrg } 5682ddb6cf1Smrg else if (AngleBetween(angle, a[2], a[3])) 5692ddb6cf1Smrg { 5702ddb6cf1Smrg /* right */ 5712ddb6cf1Smrg dist *= dx / x1; 5722ddb6cf1Smrg } 5732ddb6cf1Smrg else if (AngleBetween(angle, a[3], a[0])) 5742ddb6cf1Smrg { 5752ddb6cf1Smrg /* top */ 5762ddb6cf1Smrg dist *= dy / y0; 5772ddb6cf1Smrg } 5782ddb6cf1Smrg if (dist > BALL_DIST) 5792ddb6cf1Smrg dist = BALL_DIST; 5802ddb6cf1Smrg } 581a1d141d5Smrg if (dist > hypot ((double) dx, (double) dy)) { 5822ddb6cf1Smrg cx += dx; 5832ddb6cf1Smrg cy += dy; 584a1d141d5Smrg } else { 5852ddb6cf1Smrg cx += dist * cosa; 5862ddb6cf1Smrg cy += dist * sina; 587a1d141d5Smrg } 588a1d141d5Smrg } 589a1d141d5Smrg ret.x = cx; 590a1d141d5Smrg ret.y = cy; 591a1d141d5Smrg return ret; 592a1d141d5Smrg} 593a1d141d5Smrg 594a1d141d5Smrgstatic void computePupils ( 5952ddb6cf1Smrg EyesWidget w, 596a1d141d5Smrg TPoint mouse, 597a1d141d5Smrg TPoint pupils[2]) 598a1d141d5Smrg{ 5992ddb6cf1Smrg TRectangle screen, *sp = NULL; 6002ddb6cf1Smrg if (w->eyes.distance) { 6012ddb6cf1Smrg Window r, cw; 6022ddb6cf1Smrg int x, y; 6032ddb6cf1Smrg r = RootWindowOfScreen(w->core.screen); 6042ddb6cf1Smrg XTranslateCoordinates(XtDisplay(w), XtWindow(w), r, 0, 0, &x, &y, &cw); 6052ddb6cf1Smrg screen.x = Tx(-x, -y, &w->eyes.t); 6062ddb6cf1Smrg screen.y = Ty(-x, -y, &w->eyes.t); 6072ddb6cf1Smrg screen.width = Twidth (w->core.screen->width, w->core.screen->height, 6082ddb6cf1Smrg &w->eyes.t); 6092ddb6cf1Smrg screen.height = Theight(w->core.screen->width, w->core.screen->height, 6102ddb6cf1Smrg &w->eyes.t); 6112ddb6cf1Smrg sp = &screen; 6122ddb6cf1Smrg } 6132ddb6cf1Smrg pupils[0] = computePupil (0, mouse, sp); 6142ddb6cf1Smrg pupils[1] = computePupil (1, mouse, sp); 615a1d141d5Smrg} 616a1d141d5Smrg 6172ddb6cf1Smrgstatic void 6182ddb6cf1SmrgeyeBall(EyesWidget w, 6192ddb6cf1Smrg Boolean draw, 6202ddb6cf1Smrg TPoint *old, 6212ddb6cf1Smrg int num) 622a1d141d5Smrg{ 6232ddb6cf1Smrg drawEllipse(w, draw ? PART_PUPIL : PART_CLEAR, 6242ddb6cf1Smrg w->eyes.pupil[num].x, w->eyes.pupil[num].y, 6252ddb6cf1Smrg old ? old->x : TPOINT_NONE, old ? old->y : TPOINT_NONE, 6262ddb6cf1Smrg BALL_DIAM); 627a1d141d5Smrg} 628a1d141d5Smrg 629a1d141d5Smrgstatic void repaint_window (EyesWidget w) 630a1d141d5Smrg{ 631a1d141d5Smrg if (XtIsRealized ((Widget) w)) { 63226df5c7cSmrg#ifdef PRESENT 63326df5c7cSmrg MakePresentData(w); 63426df5c7cSmrg#endif 6352ddb6cf1Smrg eyeLiner (w, TRUE, 0); 6362ddb6cf1Smrg eyeLiner (w, TRUE, 1); 6372ddb6cf1Smrg computePupils (w, w->eyes.mouse, w->eyes.pupil); 6382ddb6cf1Smrg eyeBall (w, TRUE, NULL, 0); 6392ddb6cf1Smrg eyeBall (w, TRUE, NULL, 1); 64026df5c7cSmrg#ifdef PRESENT 64126df5c7cSmrg UpdatePresent(w); 64226df5c7cSmrg#endif 643a1d141d5Smrg } 644a1d141d5Smrg} 645a1d141d5Smrg 6462ddb6cf1Smrgstatic void 6472ddb6cf1SmrgdrawEye(EyesWidget w, TPoint newpupil, int num) 6482ddb6cf1Smrg{ 6492ddb6cf1Smrg XPoint xnewpupil, xpupil; 6502ddb6cf1Smrg 6512ddb6cf1Smrg xpupil.x = Xx(w->eyes.pupil[num].x, w->eyes.pupil[num].y, &w->eyes.t); 6522ddb6cf1Smrg xpupil.y = Xy(w->eyes.pupil[num].x, w->eyes.pupil[num].y, &w->eyes.t); 6532ddb6cf1Smrg xnewpupil.x = Xx(newpupil.x, newpupil.y, &w->eyes.t); 6542ddb6cf1Smrg xnewpupil.y = Xy(newpupil.x, newpupil.y, &w->eyes.t); 6552ddb6cf1Smrg if ( 6562ddb6cf1Smrg#ifdef XRENDER 6572ddb6cf1Smrg w->eyes.picture ? !TPointEqual(w->eyes.pupil[num], newpupil) : 6582ddb6cf1Smrg#endif 6592ddb6cf1Smrg !XPointEqual(xpupil, xnewpupil)) { 6602ddb6cf1Smrg TPoint oldpupil = w->eyes.pupil[num]; 6612ddb6cf1Smrg w->eyes.pupil[num] = newpupil; 6622ddb6cf1Smrg eyeBall (w, TRUE, &oldpupil, num); 6632ddb6cf1Smrg } 6642ddb6cf1Smrg} 6652ddb6cf1Smrg 6662ddb6cf1Smrgstatic void 6672ddb6cf1SmrgdrawEyes(EyesWidget w, TPoint mouse) 6682ddb6cf1Smrg{ 6692ddb6cf1Smrg TPoint newpupil[2]; 6702ddb6cf1Smrg int num; 6712ddb6cf1Smrg 67226df5c7cSmrg#ifdef PRESENT 67326df5c7cSmrg MakePresentData(w); 67426df5c7cSmrg#endif 6752ddb6cf1Smrg if (TPointEqual (mouse, w->eyes.mouse)) { 6762ddb6cf1Smrg if (delays[w->eyes.update + 1] != 0) 6772ddb6cf1Smrg ++w->eyes.update; 6782ddb6cf1Smrg return; 6792ddb6cf1Smrg } 6802ddb6cf1Smrg computePupils (w, mouse, newpupil); 6812ddb6cf1Smrg for (num = 0; num < 2; num ++) { 6822ddb6cf1Smrg drawEye(w, newpupil[num], num); 6832ddb6cf1Smrg } 6842ddb6cf1Smrg 6852ddb6cf1Smrg w->eyes.mouse = mouse; 6862ddb6cf1Smrg w->eyes.update = 0; 68726df5c7cSmrg#ifdef PRESENT 68826df5c7cSmrg UpdatePresent(w); 68926df5c7cSmrg#endif 6902ddb6cf1Smrg} 6912ddb6cf1Smrg 6922ddb6cf1Smrgstatic void draw_it_core(EyesWidget w) 6932ddb6cf1Smrg{ 6942ddb6cf1Smrg Window rep_root, rep_child; 6952ddb6cf1Smrg int rep_rootx, rep_rooty; 6962ddb6cf1Smrg unsigned int rep_mask; 6972ddb6cf1Smrg int dx, dy; 6982ddb6cf1Smrg TPoint mouse; 6992ddb6cf1Smrg Display *dpy = XtDisplay (w); 7002ddb6cf1Smrg Window win = XtWindow (w); 7012ddb6cf1Smrg 7022ddb6cf1Smrg XQueryPointer (dpy, win, &rep_root, &rep_child, 7032ddb6cf1Smrg &rep_rootx, &rep_rooty, &dx, &dy, &rep_mask); 7042ddb6cf1Smrg mouse.x = Tx(dx, dy, &w->eyes.t); 7052ddb6cf1Smrg mouse.y = Ty(dx, dy, &w->eyes.t); 7062ddb6cf1Smrg 7072ddb6cf1Smrg drawEyes(w, mouse); 7082ddb6cf1Smrg} 7092ddb6cf1Smrg 710a1d141d5Smrg/* ARGSUSED */ 711a1d141d5Smrgstatic void draw_it ( 712a1d141d5Smrg XtPointer client_data, 713a1d141d5Smrg XtIntervalId *id) /* unused */ 714a1d141d5Smrg{ 715a1d141d5Smrg EyesWidget w = (EyesWidget)client_data; 716a1d141d5Smrg 717a1d141d5Smrg if (XtIsRealized((Widget)w)) { 7182ddb6cf1Smrg draw_it_core(w); 719a1d141d5Smrg } 72026df5c7cSmrg if (!w->eyes.has_xi2) { 72126df5c7cSmrg w->eyes.interval_id = 72226df5c7cSmrg XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w), 72326df5c7cSmrg delays[w->eyes.update], draw_it, (XtPointer)w); 72426df5c7cSmrg } 725a1d141d5Smrg} /* draw_it */ 726a1d141d5Smrg 727a1d141d5Smrgstatic void Resize (Widget gw) 728a1d141d5Smrg{ 729a1d141d5Smrg EyesWidget w = (EyesWidget) gw; 730a1d141d5Smrg XGCValues xgcv; 731a1d141d5Smrg Widget parent; 7322ddb6cf1Smrg Display *dpy = XtDisplay (w); 733a1d141d5Smrg int x, y; 734a1d141d5Smrg 735a1d141d5Smrg if (XtIsRealized (gw)) 736a1d141d5Smrg { 737a1d141d5Smrg SetTransform (&w->eyes.t, 738a1d141d5Smrg 0, w->core.width, 739a1d141d5Smrg w->core.height, 0, 740a1d141d5Smrg W_MIN_X, W_MAX_X, 741a1d141d5Smrg W_MIN_Y, W_MAX_Y); 74226df5c7cSmrg#ifdef PRESENT 74326df5c7cSmrg if (w->eyes.back_buffer) { 74426df5c7cSmrg xcb_free_pixmap(xt_xcb(w), 74526df5c7cSmrg w->eyes.back_buffer); 74626df5c7cSmrg w->eyes.back_buffer = None; 74726df5c7cSmrg xcb_damage_destroy(xt_xcb(w), 74826df5c7cSmrg w->eyes.back_damage); 74926df5c7cSmrg w->eyes.back_damage = None; 75026df5c7cSmrg } 75126df5c7cSmrg MakePresentData(w); 75226df5c7cSmrg#endif 75326df5c7cSmrg if (EyesDrawable(w) == XtWindow(w)) 75426df5c7cSmrg XClearWindow (dpy, XtWindow (w)); 75526df5c7cSmrg 7562ddb6cf1Smrg#ifdef XRENDER 7572ddb6cf1Smrg if (w->eyes.picture) { 7582ddb6cf1Smrg XRenderFreePicture(dpy, w->eyes.picture); 7592ddb6cf1Smrg w->eyes.picture = 0; 7602ddb6cf1Smrg } 7612ddb6cf1Smrg#endif 762a1d141d5Smrg if (w->eyes.shape_window) { 7632ddb6cf1Smrg w->eyes.shape_mask = XCreatePixmap (dpy, XtWindow (w), 764a1d141d5Smrg w->core.width, w->core.height, 1); 7652ddb6cf1Smrg if (!w->eyes.gc[PART_SHAPE]) 7662ddb6cf1Smrg w->eyes.gc[PART_SHAPE] = XCreateGC (dpy, w->eyes.shape_mask, 7672ddb6cf1Smrg 0, &xgcv); 7682ddb6cf1Smrg XSetForeground (dpy, w->eyes.gc[PART_SHAPE], 0); 7692ddb6cf1Smrg XFillRectangle (dpy, w->eyes.shape_mask, w->eyes.gc[PART_SHAPE], 7702ddb6cf1Smrg 0, 0, w->core.width, w->core.height); 7712ddb6cf1Smrg XSetForeground (dpy, w->eyes.gc[PART_SHAPE], 1); 7722ddb6cf1Smrg eyeLiner (w, FALSE, 0); 7732ddb6cf1Smrg eyeLiner (w, FALSE, 1); 774a1d141d5Smrg x = y = 0; 775a1d141d5Smrg for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) { 776a1d141d5Smrg x += parent->core.x + parent->core.border_width; 777a1d141d5Smrg x += parent->core.y + parent->core.border_width; 778a1d141d5Smrg } 779a1d141d5Smrg XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding, 780a1d141d5Smrg x, y, w->eyes.shape_mask, ShapeSet); 7812ddb6cf1Smrg XFreePixmap (dpy, w->eyes.shape_mask); 782a1d141d5Smrg } 7832ddb6cf1Smrg#ifdef XRENDER 7842ddb6cf1Smrg if (w->eyes.render) { 7852ddb6cf1Smrg XRenderPictureAttributes pa; 7862ddb6cf1Smrg XRenderPictFormat *pf; 7872ddb6cf1Smrg pf = XRenderFindVisualFormat(dpy, 7882ddb6cf1Smrg DefaultVisualOfScreen(w->core.screen)); 7892ddb6cf1Smrg if (pf) 79026df5c7cSmrg w->eyes.picture = XRenderCreatePicture(dpy, EyesDrawable (w), 7912ddb6cf1Smrg pf, 0, &pa); 7922ddb6cf1Smrg } 7932ddb6cf1Smrg#endif 794a1d141d5Smrg } 795a1d141d5Smrg} 796a1d141d5Smrg 797a1d141d5Smrgstatic void Realize ( 798a1d141d5Smrg Widget gw, 799a1d141d5Smrg XtValueMask *valueMask, 800a1d141d5Smrg XSetWindowAttributes *attrs) 801a1d141d5Smrg{ 802a1d141d5Smrg EyesWidget w = (EyesWidget)gw; 803a1d141d5Smrg 804a1d141d5Smrg if (w->eyes.backing_store != Always + WhenMapped + NotUseful) { 805a1d141d5Smrg attrs->backing_store = w->eyes.backing_store; 806a1d141d5Smrg *valueMask |= CWBackingStore; 807a1d141d5Smrg } 808a1d141d5Smrg XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent, 809a1d141d5Smrg *valueMask, attrs ); 810a1d141d5Smrg Resize (gw); 81126df5c7cSmrg 81226df5c7cSmrg if (w->eyes.has_xi2) 81326df5c7cSmrg xi2_add_root_listener(gw); 81426df5c7cSmrg else 81526df5c7cSmrg w->eyes.interval_id = 81626df5c7cSmrg XtAppAddTimeOut(XtWidgetToApplicationContext(gw), 81726df5c7cSmrg delays[w->eyes.update], draw_it, (XtPointer)gw); 818a1d141d5Smrg} 819a1d141d5Smrg 820a1d141d5Smrgstatic void Destroy (Widget gw) 821a1d141d5Smrg{ 822a1d141d5Smrg EyesWidget w = (EyesWidget)gw; 8232ddb6cf1Smrg int i; 824a1d141d5Smrg 825a1d141d5Smrg if (w->eyes.interval_id) 826a1d141d5Smrg XtRemoveTimeOut (w->eyes.interval_id); 8272ddb6cf1Smrg for (i = 0; i < PART_MAX; i ++) 8282ddb6cf1Smrg XtReleaseGC(gw, w->eyes.gc[i]); 82926df5c7cSmrg xi2_remove_root_listener(gw); 8302ddb6cf1Smrg#ifdef XRENDER 8312ddb6cf1Smrg if (w->eyes.picture) 8322ddb6cf1Smrg XRenderFreePicture (XtDisplay(w), w->eyes.picture); 8332ddb6cf1Smrg#endif 834a1d141d5Smrg} 835a1d141d5Smrg 836a1d141d5Smrg/* ARGSUSED */ 837a1d141d5Smrgstatic void Redisplay( 838a1d141d5Smrg Widget gw, 839a1d141d5Smrg XEvent *event, 840a1d141d5Smrg Region region) 841a1d141d5Smrg{ 842a1d141d5Smrg EyesWidget w; 843a1d141d5Smrg 844a1d141d5Smrg w = (EyesWidget) gw; 8452ddb6cf1Smrg w->eyes.pupil[0].x = TPOINT_NONE; 8462ddb6cf1Smrg w->eyes.pupil[0].y = TPOINT_NONE; 8472ddb6cf1Smrg w->eyes.pupil[1].x = TPOINT_NONE; 8482ddb6cf1Smrg w->eyes.pupil[1].y = TPOINT_NONE; 849a1d141d5Smrg (void) repaint_window ((EyesWidget)gw); 850a1d141d5Smrg} 851a1d141d5Smrg 852a1d141d5Smrg/* ARGSUSED */ 853a1d141d5Smrgstatic Boolean SetValues ( 854a1d141d5Smrg Widget current, 855a1d141d5Smrg Widget request, 856a1d141d5Smrg Widget new, 857a1d141d5Smrg ArgList args, 858a1d141d5Smrg Cardinal *num_args) 859a1d141d5Smrg{ 860a1d141d5Smrg return( FALSE ); 861a1d141d5Smrg} 862a1d141d5Smrg 863a1d141d5SmrgEyesClassRec eyesClassRec = { 864a1d141d5Smrg { /* core fields */ 865a1d141d5Smrg /* superclass */ &widgetClassRec, 86626df5c7cSmrg /* class_name */ (char *) "Eyes", 867a1d141d5Smrg /* size */ sizeof(EyesRec), 868a1d141d5Smrg /* class_initialize */ ClassInitialize, 869a1d141d5Smrg /* class_part_initialize */ NULL, 870a1d141d5Smrg /* class_inited */ FALSE, 871a1d141d5Smrg /* initialize */ Initialize, 872a1d141d5Smrg /* initialize_hook */ NULL, 873a1d141d5Smrg /* realize */ Realize, 874a1d141d5Smrg /* actions */ NULL, 875a1d141d5Smrg /* num_actions */ 0, 876a1d141d5Smrg /* resources */ resources, 877a1d141d5Smrg /* num_resources */ XtNumber(resources), 878a1d141d5Smrg /* xrm_class */ NULLQUARK, 879a1d141d5Smrg /* compress_motion */ TRUE, 880a1d141d5Smrg /* compress_exposure */ TRUE, 881a1d141d5Smrg /* compress_enterleave */ TRUE, 882a1d141d5Smrg /* visible_interest */ FALSE, 883a1d141d5Smrg /* destroy */ Destroy, 884a1d141d5Smrg /* resize */ Resize, 885a1d141d5Smrg /* expose */ Redisplay, 886a1d141d5Smrg /* set_values */ SetValues, 887a1d141d5Smrg /* set_values_hook */ NULL, 888a1d141d5Smrg /* set_values_almost */ NULL, 889a1d141d5Smrg /* get_values_hook */ NULL, 890a1d141d5Smrg /* accept_focus */ NULL, 891a1d141d5Smrg /* version */ XtVersion, 892a1d141d5Smrg /* callback_private */ NULL, 893a1d141d5Smrg /* tm_table */ NULL, 894a1d141d5Smrg /* query_geometry */ XtInheritQueryGeometry, 895a1d141d5Smrg } 896a1d141d5Smrg}; 897