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