Logo.c revision 3a99fc18
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 /* extension */ NULL 116 }, 117 { /* logo fields */ 118 /* ignore */ 0 119 } 120}; 121 122WidgetClass logoWidgetClass = (WidgetClass) &logoClassRec; 123 124 125/***************************************************************************** 126 * * 127 * private utility routines * 128 * * 129 *****************************************************************************/ 130 131static void 132create_gcs(LogoWidget w) 133{ 134 XGCValues v; 135 136#ifdef XRENDER 137 w->logo.fgpixel = w->logo.fg.pixel; 138#endif 139 140 v.foreground = w->logo.fgpixel; 141 w->logo.foreGC = XtGetGC ((Widget) w, GCForeground, &v); 142 v.foreground = w->core.background_pixel; 143 w->logo.backGC = XtGetGC ((Widget) w, GCForeground, &v); 144} 145 146static void 147check_shape(LogoWidget w) 148{ 149 if (w->logo.shape_window) { 150 int event_base, error_base; 151 152 if (!XShapeQueryExtension (XtDisplay (w), &event_base, &error_base)) 153 w->logo.shape_window = FALSE; 154 } 155} 156 157/* ARGSUSED */ 158static void 159unset_shape(LogoWidget w) 160{ 161 XSetWindowAttributes attr; 162 unsigned long mask; 163 Display *dpy = XtDisplay ((Widget) w); 164 Window win = XtWindow ((Widget) w); 165 166 if (w->core.background_pixmap != None && 167 w->core.background_pixmap != XtUnspecifiedPixmap) { 168 attr.background_pixmap = w->core.background_pixmap; 169 mask = CWBackPixmap; 170 } else { 171 attr.background_pixel = w->core.background_pixel; 172 mask = CWBackPixel; 173 } 174 XChangeWindowAttributes (dpy, win, mask, &attr); 175 XShapeCombineMask (dpy, win, ShapeBounding, 0, 0, None, ShapeSet); 176 if (!w->logo.foreGC) create_gcs (w); 177 w->logo.need_shaping = w->logo.shape_window; 178} 179 180static void 181set_shape(LogoWidget w) 182{ 183 GC ones, zeros; 184 Display *dpy = XtDisplay ((Widget) w); 185 Window win = XtWindow ((Widget) w); 186 unsigned int width = (unsigned int) w->core.width; 187 unsigned int height = (unsigned int) w->core.height; 188 Pixmap pm = XCreatePixmap (dpy, win, width, height, (unsigned int) 1); 189 XGCValues v; 190 191 v.foreground = (Pixel) 1; 192 v.background = (Pixel) 0; 193 ones = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v); 194 v.foreground = (Pixel) 0; 195 v.background = (Pixel) 1; 196 zeros = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v); 197 198 if (pm && ones && zeros) { 199 int x = 0, y = 0; 200 Widget parent; 201 202 XmuDrawLogo (dpy, pm, ones, zeros, 0, 0, width, height); 203 for (parent = (Widget) w; XtParent(parent); 204 parent = XtParent(parent)) { 205 x += parent->core.x + parent->core.border_width; 206 y += parent->core.y + parent->core.border_width; 207 } 208 XShapeCombineMask (dpy, XtWindow (parent), ShapeBounding, 209 x, y, pm, ShapeSet); 210 w->logo.need_shaping = FALSE; 211 } else { 212 unset_shape (w); 213 } 214 if (ones) XFreeGC (dpy, ones); 215 if (zeros) XFreeGC (dpy, zeros); 216 if (pm) XFreePixmap (dpy, pm); 217} 218 219 220/***************************************************************************** 221 * * 222 * class methods * 223 * * 224 *****************************************************************************/ 225 226#ifdef XRENDER 227 228static void 229RenderPrepare (LogoWidget w) 230{ 231 if (!w->logo.draw) 232 { 233 w->logo.draw = XftDrawCreate (XtDisplay (w), XtWindow (w), 234 DefaultVisual (XtDisplay (w), 235 DefaultScreen(XtDisplay (w))), 236 w->core.colormap); 237 } 238} 239 240static XtConvertArgRec xftColorConvertArgs[] = { 241 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 242 sizeof(Screen *)}, 243 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 244 sizeof(Colormap)} 245}; 246 247#define donestr(type, value, tstr) \ 248 { \ 249 if (toVal->addr != NULL) { \ 250 if (toVal->size < sizeof(type)) { \ 251 toVal->size = sizeof(type); \ 252 XtDisplayStringConversionWarning(dpy, \ 253 (char*) fromVal->addr, tstr); \ 254 return False; \ 255 } \ 256 *(type*)(toVal->addr) = (value); \ 257 } \ 258 else { \ 259 static type static_val; \ 260 static_val = (value); \ 261 toVal->addr = (XPointer)&static_val; \ 262 } \ 263 toVal->size = sizeof(type); \ 264 return True; \ 265 } 266 267static void 268XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, 269 XrmValuePtr args, Cardinal *num_args) 270{ 271 Screen *screen; 272 Colormap colormap; 273 XftColor *color; 274 275 if (*num_args != 2) 276 { 277 XtAppErrorMsg (app, 278 "freeXftColor", "wrongParameters", 279 "XtToolkitError", 280 "Freeing an XftColor requires screen and colormap arguments", 281 (String *) NULL, (Cardinal *)NULL); 282 return; 283 } 284 285 screen = *((Screen **) args[0].addr); 286 colormap = *((Colormap *) args[1].addr); 287 color = (XftColor *) toVal->addr; 288 XftColorFree (DisplayOfScreen (screen), 289 DefaultVisual (DisplayOfScreen (screen), 290 XScreenNumberOfScreen (screen)), 291 colormap, color); 292} 293 294static Boolean 295XmuCvtStringToXftColor(Display *dpy, 296 XrmValue *args, Cardinal *num_args, 297 XrmValue *fromVal, XrmValue *toVal, 298 XtPointer *converter_data) 299{ 300 char *spec; 301 XRenderColor renderColor; 302 XftColor xftColor; 303 Screen *screen; 304 Colormap colormap; 305 306 if (*num_args != 2) 307 { 308 XtAppErrorMsg (XtDisplayToApplicationContext (dpy), 309 "cvtStringToXftColor", "wrongParameters", 310 "XtToolkitError", 311 "String to render color conversion needs screen and colormap arguments", 312 (String *) NULL, (Cardinal *)NULL); 313 return False; 314 } 315 316 screen = *((Screen **) args[0].addr); 317 colormap = *((Colormap *) args[1].addr); 318 319 spec = (char *) fromVal->addr; 320 if (strcasecmp (spec, XtDefaultForeground) == 0) 321 { 322 renderColor.red = 0; 323 renderColor.green = 0; 324 renderColor.blue = 0; 325 renderColor.alpha = 0xffff; 326 } 327 else if (strcasecmp (spec, XtDefaultBackground) == 0) 328 { 329 renderColor.red = 0xffff; 330 renderColor.green = 0xffff; 331 renderColor.blue = 0xffff; 332 renderColor.alpha = 0xffff; 333 } 334 else if (!XRenderParseColor (dpy, spec, &renderColor)) 335 return False; 336 if (!XftColorAllocValue (dpy, 337 DefaultVisual (dpy, 338 XScreenNumberOfScreen (screen)), 339 colormap, 340 &renderColor, 341 &xftColor)) 342 return False; 343 344 donestr (XftColor, xftColor, XtRXftColor); 345} 346 347 348#endif 349 350static void 351ClassInitialize(void) 352{ 353#ifdef XRENDER 354 XtSetTypeConverter (XtRString, XtRXftColor, 355 XmuCvtStringToXftColor, 356 xftColorConvertArgs, XtNumber(xftColorConvertArgs), 357 XtCacheByDisplay, XmuFreeXftColor); 358#endif 359} 360 361/* ARGSUSED */ 362static void 363Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) 364{ 365 LogoWidget w = (LogoWidget)new; 366 367#ifdef XRENDER 368 w->logo.draw = NULL; 369 w->logo.fgpixel = w->logo.fg.pixel; 370#endif 371 if (w->core.width < 1) w->core.width = 100; 372 if (w->core.height < 1) w->core.height = 100; 373 374 w->logo.foreGC = (GC) NULL; 375 w->logo.backGC = (GC) NULL; 376 check_shape (w); 377 w->logo.need_shaping = w->logo.shape_window; 378} 379 380static void 381Destroy(Widget gw) 382{ 383 LogoWidget w = (LogoWidget) gw; 384 if (w->logo.foreGC) { 385 XtReleaseGC (gw, w->logo.foreGC); 386 w->logo.foreGC = (GC) NULL; 387 } 388 if (w->logo.backGC) { 389 XtReleaseGC (gw, w->logo.backGC); 390 w->logo.backGC = (GC) NULL; 391 } 392} 393 394static void 395Realize(Widget gw, XtValueMask *valuemaskp, XSetWindowAttributes *attr) 396{ 397 LogoWidget w = (LogoWidget) gw; 398 399 if (w->logo.shape_window) { 400 attr->background_pixel = w->logo.fgpixel; /* going to shape */ 401 *valuemaskp |= CWBackPixel; 402 } else 403 create_gcs (w); 404 (*logoWidgetClass->core_class.superclass->core_class.realize) 405 (gw, valuemaskp, attr); 406} 407 408static void 409Resize(Widget gw) 410{ 411 LogoWidget w = (LogoWidget) gw; 412 413 if (w->logo.shape_window && XtIsRealized(gw)) set_shape (w); 414} 415 416/* ARGSUSED */ 417static void 418Redisplay(Widget gw, XEvent *event, Region region) 419{ 420 LogoWidget w = (LogoWidget) gw; 421 422 if (w->logo.shape_window) { 423 if (w->logo.need_shaping) set_shape (w); /* may change shape flag */ 424 } 425 if (!w->logo.shape_window) { 426#ifdef XRENDER 427 if (w->logo.render) 428 { 429 RenderPrepare (w); 430 431 XClearWindow (XtDisplay(w), XtWindow(w)); 432 RenderLogo (XtDisplay(w), PictOpOver, 433 XftDrawSrcPicture (w->logo.draw, &w->logo.fg), 434 XftDrawPicture (w->logo.draw), 435 XRenderFindStandardFormat (XtDisplay (w), 436 w->logo.sharp ? 437 PictStandardA1: 438 PictStandardA8), 439 0, 0, (unsigned int) w->core.width, 440 (unsigned int) w->core.height); 441 } 442 else 443#endif 444 { 445 XmuDrawLogo (XtDisplay(w), XtWindow(w), w->logo.foreGC, w->logo.backGC, 446 0, 0, (unsigned int) w->core.width, 447 (unsigned int) w->core.height); 448 } 449 } 450} 451 452/* ARGSUSED */ 453static Boolean 454SetValues (Widget gcurrent, Widget grequest, Widget gnew, 455 ArgList args, Cardinal *num_args) 456{ 457 LogoWidget current = (LogoWidget) gcurrent; 458 LogoWidget new = (LogoWidget) gnew; 459 Boolean redisplay = FALSE; 460 461 if (new->logo.shape_window && 462 new->logo.shape_window != current->logo.shape_window) 463 check_shape (new); /* validate shape_window */ 464 465 if ((new->logo.fgpixel != current->logo.fgpixel) || 466 (new->core.background_pixel != current->core.background_pixel)) { 467 Destroy (gnew); 468 if (!new->logo.shape_window) create_gcs (new); 469 redisplay = TRUE; 470 } 471 472 if (new->logo.shape_window != current->logo.shape_window) { 473 if (new->logo.shape_window) { 474 Destroy (gnew); 475 if (XtIsRealized(gnew)) 476 set_shape (new); 477 else 478 new->logo.need_shaping = True; 479 redisplay = FALSE; 480 } else { 481 if (XtIsRealized(gnew)) 482 unset_shape (new); /* creates new GCs */ 483 redisplay = TRUE; 484 } 485 } 486 487 return (redisplay); 488} 489