Logo.c revision e531b1a7
1/* 2 3Copyright 1988, 1994, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <X11/StringDefs.h> 33#include <X11/IntrinsicP.h> 34#include <X11/Xmu/Drawing.h> 35#include "LogoP.h" 36#include <X11/extensions/shape.h> 37#include <X11/Xos.h> 38 39#ifdef XRENDER 40#include "RenderLogo.h" 41#endif 42 43static XtResource resources[] = { 44 {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean), 45 XtOffsetOf(LogoRec,logo.shape_window), XtRImmediate, 46 (XtPointer) FALSE}, 47#ifdef XRENDER 48 {XtNrender, XtCBoolean, XtRBoolean, sizeof(Boolean), 49 XtOffsetOf(LogoRec,logo.render), XtRImmediate, 50 (XtPointer) FALSE }, 51 {XtNsharp, XtCBoolean, XtRBoolean, sizeof(Boolean), 52 XtOffsetOf(LogoRec,logo.sharp), XtRImmediate, 53 (XtPointer) FALSE }, 54 {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), 55 XtOffsetOf(LogoRec, logo.fg), XtRString, 56 (XtPointer) XtDefaultForeground}, 57 {XtNbackground, XtCForeground, XtRXftColor, sizeof(XftColor), 58 XtOffsetOf(LogoRec, logo.bg), XtRString, 59 (XtPointer) XtDefaultBackground}, 60#else 61 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 62 XtOffsetOf(LogoRec,logo.fgpixel), XtRString, 63 (XtPointer) XtDefaultForeground}, 64#endif 65}; 66 67static void ClassInitialize ( void ); 68static void Initialize ( Widget request, Widget new, ArgList args, 69 Cardinal *num_args ); 70static void Destroy ( Widget gw ); 71static void Realize ( Widget gw, XtValueMask *valuemaskp, 72 XSetWindowAttributes *attr ); 73static void Resize ( Widget gw ); 74static void Redisplay ( Widget gw, XEvent *event, Region region ); 75static Boolean SetValues ( Widget gcurrent, Widget grequest, Widget gnew, 76 ArgList args, Cardinal *num_args ); 77 78LogoClassRec logoClassRec = { 79 { /* core fields */ 80 /* superclass */ (WidgetClass) &simpleClassRec, 81 /* class_name */ "Logo", 82 /* widget_size */ sizeof(LogoRec), 83 /* class_initialize */ ClassInitialize, 84 /* class_part_initialize */ NULL, 85 /* class_inited */ FALSE, 86 /* initialize */ Initialize, 87 /* initialize_hook */ NULL, 88 /* realize */ Realize, 89 /* actions */ NULL, 90 /* num_actions */ 0, 91 /* resources */ resources, 92 /* resource_count */ XtNumber(resources), 93 /* xrm_class */ NULLQUARK, 94 /* compress_motion */ TRUE, 95 /* compress_exposure */ TRUE, 96 /* compress_enterleave */ TRUE, 97 /* visible_interest */ FALSE, 98 /* destroy */ Destroy, 99 /* resize */ Resize, 100 /* expose */ Redisplay, 101 /* set_values */ SetValues, 102 /* set_values_hook */ NULL, 103 /* set_values_almost */ XtInheritSetValuesAlmost, 104 /* get_values_hook */ NULL, 105 /* accept_focus */ NULL, 106 /* version */ XtVersion, 107 /* callback_private */ NULL, 108 /* tm_table */ NULL, 109 /* query_geometry */ XtInheritQueryGeometry, 110 /* display_accelerator */ XtInheritDisplayAccelerator, 111 /* extension */ NULL 112 }, 113 { /* simple fields */ 114 /* change_sensitive */ XtInheritChangeSensitive 115 }, 116 { /* logo fields */ 117 /* ignore */ 0 118 } 119}; 120 121WidgetClass logoWidgetClass = (WidgetClass) &logoClassRec; 122 123 124/***************************************************************************** 125 * * 126 * private utility routines * 127 * * 128 *****************************************************************************/ 129 130static void 131create_gcs(LogoWidget w) 132{ 133 XGCValues v; 134 135#ifdef XRENDER 136 w->logo.fgpixel = w->logo.fg.pixel; 137#endif 138 139 v.foreground = w->logo.fgpixel; 140 w->logo.foreGC = XtGetGC ((Widget) w, GCForeground, &v); 141 v.foreground = w->core.background_pixel; 142 w->logo.backGC = XtGetGC ((Widget) w, GCForeground, &v); 143} 144 145static void 146check_shape(LogoWidget w) 147{ 148 if (w->logo.shape_window) { 149 int event_base, error_base; 150 151 if (!XShapeQueryExtension (XtDisplay (w), &event_base, &error_base)) 152 w->logo.shape_window = FALSE; 153 } 154} 155 156/* ARGSUSED */ 157static void 158unset_shape(LogoWidget w) 159{ 160 XSetWindowAttributes attr; 161 unsigned long mask; 162 Display *dpy = XtDisplay ((Widget) w); 163 Window win = XtWindow ((Widget) w); 164 165 if (w->core.background_pixmap != None && 166 w->core.background_pixmap != XtUnspecifiedPixmap) { 167 attr.background_pixmap = w->core.background_pixmap; 168 mask = CWBackPixmap; 169 } else { 170 attr.background_pixel = w->core.background_pixel; 171 mask = CWBackPixel; 172 } 173 XChangeWindowAttributes (dpy, win, mask, &attr); 174 XShapeCombineMask (dpy, win, ShapeBounding, 0, 0, None, ShapeSet); 175 if (!w->logo.foreGC) create_gcs (w); 176 w->logo.need_shaping = w->logo.shape_window; 177} 178 179static void 180set_shape(LogoWidget w) 181{ 182 GC ones, zeros; 183 Display *dpy = XtDisplay ((Widget) w); 184 Window win = XtWindow ((Widget) w); 185 unsigned int width = (unsigned int) w->core.width; 186 unsigned int height = (unsigned int) w->core.height; 187 Pixmap pm = XCreatePixmap (dpy, win, width, height, (unsigned int) 1); 188 XGCValues v; 189 190 v.foreground = (Pixel) 1; 191 v.background = (Pixel) 0; 192 ones = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v); 193 v.foreground = (Pixel) 0; 194 v.background = (Pixel) 1; 195 zeros = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v); 196 197 if (pm && ones && zeros) { 198 int x = 0, y = 0; 199 Widget parent; 200 201 XmuDrawLogo (dpy, pm, ones, zeros, 0, 0, width, height); 202 for (parent = (Widget) w; XtParent(parent); 203 parent = XtParent(parent)) { 204 x += parent->core.x + parent->core.border_width; 205 y += parent->core.y + parent->core.border_width; 206 } 207 XShapeCombineMask (dpy, XtWindow (parent), ShapeBounding, 208 x, y, pm, ShapeSet); 209 w->logo.need_shaping = FALSE; 210 } else { 211 unset_shape (w); 212 } 213 if (ones) XFreeGC (dpy, ones); 214 if (zeros) XFreeGC (dpy, zeros); 215 if (pm) XFreePixmap (dpy, pm); 216} 217 218 219/***************************************************************************** 220 * * 221 * class methods * 222 * * 223 *****************************************************************************/ 224 225#ifdef XRENDER 226 227static void 228RenderPrepare (LogoWidget w) 229{ 230 if (!w->logo.draw) 231 { 232 w->logo.draw = XftDrawCreate (XtDisplay (w), XtWindow (w), 233 DefaultVisual (XtDisplay (w), 234 DefaultScreen(XtDisplay (w))), 235 w->core.colormap); 236 } 237} 238 239static XtConvertArgRec xftColorConvertArgs[] = { 240 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 241 sizeof(Screen *)}, 242 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 243 sizeof(Colormap)} 244}; 245 246#define donestr(type, value, tstr) \ 247 { \ 248 if (toVal->addr != NULL) { \ 249 if (toVal->size < sizeof(type)) { \ 250 toVal->size = sizeof(type); \ 251 XtDisplayStringConversionWarning(dpy, \ 252 (char*) fromVal->addr, tstr); \ 253 return False; \ 254 } \ 255 *(type*)(toVal->addr) = (value); \ 256 } \ 257 else { \ 258 static type static_val; \ 259 static_val = (value); \ 260 toVal->addr = (XPointer)&static_val; \ 261 } \ 262 toVal->size = sizeof(type); \ 263 return True; \ 264 } 265 266static void 267XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, 268 XrmValuePtr args, Cardinal *num_args) 269{ 270 Screen *screen; 271 Colormap colormap; 272 XftColor *color; 273 274 if (*num_args != 2) 275 { 276 XtAppErrorMsg (app, 277 "freeXftColor", "wrongParameters", 278 "XtToolkitError", 279 "Freeing an XftColor requires screen and colormap arguments", 280 (String *) NULL, (Cardinal *)NULL); 281 return; 282 } 283 284 screen = *((Screen **) args[0].addr); 285 colormap = *((Colormap *) args[1].addr); 286 color = (XftColor *) toVal->addr; 287 XftColorFree (DisplayOfScreen (screen), 288 DefaultVisual (DisplayOfScreen (screen), 289 XScreenNumberOfScreen (screen)), 290 colormap, color); 291} 292 293static Boolean 294XmuCvtStringToXftColor(Display *dpy, 295 XrmValue *args, Cardinal *num_args, 296 XrmValue *fromVal, XrmValue *toVal, 297 XtPointer *converter_data) 298{ 299 char *spec; 300 XRenderColor renderColor; 301 XftColor xftColor; 302 Screen *screen; 303 Colormap colormap; 304 305 if (*num_args != 2) 306 { 307 XtAppErrorMsg (XtDisplayToApplicationContext (dpy), 308 "cvtStringToXftColor", "wrongParameters", 309 "XtToolkitError", 310 "String to render color conversion needs screen and colormap arguments", 311 (String *) NULL, (Cardinal *)NULL); 312 return False; 313 } 314 315 screen = *((Screen **) args[0].addr); 316 colormap = *((Colormap *) args[1].addr); 317 318 spec = (char *) fromVal->addr; 319 if (strcasecmp (spec, XtDefaultForeground) == 0) 320 { 321 renderColor.red = 0; 322 renderColor.green = 0; 323 renderColor.blue = 0; 324 renderColor.alpha = 0xffff; 325 } 326 else if (strcasecmp (spec, XtDefaultBackground) == 0) 327 { 328 renderColor.red = 0xffff; 329 renderColor.green = 0xffff; 330 renderColor.blue = 0xffff; 331 renderColor.alpha = 0xffff; 332 } 333 else if (!XRenderParseColor (dpy, spec, &renderColor)) 334 return False; 335 if (!XftColorAllocValue (dpy, 336 DefaultVisual (dpy, 337 XScreenNumberOfScreen (screen)), 338 colormap, 339 &renderColor, 340 &xftColor)) 341 return False; 342 343 donestr (XftColor, xftColor, XtRXftColor); 344} 345 346 347#endif 348 349static void 350ClassInitialize(void) 351{ 352#ifdef XRENDER 353 XtSetTypeConverter (XtRString, XtRXftColor, 354 XmuCvtStringToXftColor, 355 xftColorConvertArgs, XtNumber(xftColorConvertArgs), 356 XtCacheByDisplay, XmuFreeXftColor); 357#endif 358} 359 360/* ARGSUSED */ 361static void 362Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) 363{ 364 LogoWidget w = (LogoWidget)new; 365 366#ifdef XRENDER 367 w->logo.draw = NULL; 368 w->logo.fgpixel = w->logo.fg.pixel; 369#endif 370 if (w->core.width < 1) w->core.width = 100; 371 if (w->core.height < 1) w->core.height = 100; 372 373 w->logo.foreGC = (GC) NULL; 374 w->logo.backGC = (GC) NULL; 375 check_shape (w); 376 w->logo.need_shaping = w->logo.shape_window; 377} 378 379static void 380Destroy(Widget gw) 381{ 382 LogoWidget w = (LogoWidget) gw; 383 if (w->logo.foreGC) { 384 XtReleaseGC (gw, w->logo.foreGC); 385 w->logo.foreGC = (GC) NULL; 386 } 387 if (w->logo.backGC) { 388 XtReleaseGC (gw, w->logo.backGC); 389 w->logo.backGC = (GC) NULL; 390 } 391} 392 393static void 394Realize(Widget gw, XtValueMask *valuemaskp, XSetWindowAttributes *attr) 395{ 396 LogoWidget w = (LogoWidget) gw; 397 398 if (w->logo.shape_window) { 399 attr->background_pixel = w->logo.fgpixel; /* going to shape */ 400 *valuemaskp |= CWBackPixel; 401 } else 402 create_gcs (w); 403 (*logoWidgetClass->core_class.superclass->core_class.realize) 404 (gw, valuemaskp, attr); 405} 406 407static void 408Resize(Widget gw) 409{ 410 LogoWidget w = (LogoWidget) gw; 411 412 if (w->logo.shape_window && XtIsRealized(gw)) set_shape (w); 413} 414 415/* ARGSUSED */ 416static void 417Redisplay(Widget gw, XEvent *event, Region region) 418{ 419 LogoWidget w = (LogoWidget) gw; 420 421 if (w->logo.shape_window) { 422 if (w->logo.need_shaping) set_shape (w); /* may change shape flag */ 423 } 424 if (!w->logo.shape_window) { 425#ifdef XRENDER 426 if (w->logo.render) 427 { 428 RenderPrepare (w); 429 430 XClearWindow (XtDisplay(w), XtWindow(w)); 431 RenderLogo (XtDisplay(w), PictOpOver, 432 XftDrawSrcPicture (w->logo.draw, &w->logo.fg), 433 XftDrawPicture (w->logo.draw), 434 XRenderFindStandardFormat (XtDisplay (w), 435 w->logo.sharp ? 436 PictStandardA1: 437 PictStandardA8), 438 0, 0, (unsigned int) w->core.width, 439 (unsigned int) w->core.height); 440 } 441 else 442#endif 443 { 444 XmuDrawLogo (XtDisplay(w), XtWindow(w), w->logo.foreGC, w->logo.backGC, 445 0, 0, (unsigned int) w->core.width, 446 (unsigned int) w->core.height); 447 } 448 } 449} 450 451/* ARGSUSED */ 452static Boolean 453SetValues (Widget gcurrent, Widget grequest, Widget gnew, 454 ArgList args, Cardinal *num_args) 455{ 456 LogoWidget current = (LogoWidget) gcurrent; 457 LogoWidget new = (LogoWidget) gnew; 458 Boolean redisplay = FALSE; 459 460 if (new->logo.shape_window && 461 new->logo.shape_window != current->logo.shape_window) 462 check_shape (new); /* validate shape_window */ 463 464 if ((new->logo.fgpixel != current->logo.fgpixel) || 465 (new->core.background_pixel != current->core.background_pixel)) { 466 Destroy (gnew); 467 if (!new->logo.shape_window) create_gcs (new); 468 redisplay = TRUE; 469 } 470 471 if (new->logo.shape_window != current->logo.shape_window) { 472 if (new->logo.shape_window) { 473 Destroy (gnew); 474 if (XtIsRealized(gnew)) 475 set_shape (new); 476 else 477 new->logo.need_shaping = True; 478 redisplay = FALSE; 479 } else { 480 if (XtIsRealized(gnew)) 481 unset_shape (new); /* creates new GCs */ 482 redisplay = TRUE; 483 } 484 } 485 486 return (redisplay); 487} 488