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/Xfuncproto.h> 38#include <X11/Xos.h> 39 40#ifdef XRENDER 41#include "RenderLogo.h" 42#endif 43 44static XtResource resources[] = { 45 {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean), 46 XtOffsetOf(LogoRec,logo.shape_window), XtRImmediate, 47 (XtPointer) FALSE}, 48#ifdef XRENDER 49 {XtNrender, XtCBoolean, XtRBoolean, sizeof(Boolean), 50 XtOffsetOf(LogoRec,logo.render), XtRImmediate, 51 (XtPointer) FALSE }, 52 {XtNsharp, XtCBoolean, XtRBoolean, sizeof(Boolean), 53 XtOffsetOf(LogoRec,logo.sharp), XtRImmediate, 54 (XtPointer) FALSE }, 55 {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), 56 XtOffsetOf(LogoRec, logo.fg), XtRString, 57 (XtPointer) XtDefaultForeground}, 58 {XtNbackground, XtCForeground, XtRXftColor, sizeof(XftColor), 59 XtOffsetOf(LogoRec, logo.bg), XtRString, 60 (XtPointer) XtDefaultBackground}, 61#else 62 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 63 XtOffsetOf(LogoRec,logo.fgpixel), XtRString, 64 (XtPointer) XtDefaultForeground}, 65#endif 66}; 67 68static void ClassInitialize ( void ); 69static void Initialize ( Widget request, Widget new, ArgList args, 70 Cardinal *num_args ); 71static void Destroy ( Widget gw ); 72static void Realize ( Widget gw, XtValueMask *valuemaskp, 73 XSetWindowAttributes *attr ); 74static void Resize ( Widget gw ); 75static void Redisplay ( Widget gw, XEvent *event, Region region ); 76static Boolean SetValues ( Widget gcurrent, Widget grequest, Widget gnew, 77 ArgList args, Cardinal *num_args ); 78 79LogoClassRec logoClassRec = { 80 { /* core fields */ 81 /* superclass */ (WidgetClass) &simpleClassRec, 82 /* class_name */ "Logo", 83 /* widget_size */ sizeof(LogoRec), 84 /* class_initialize */ ClassInitialize, 85 /* class_part_initialize */ NULL, 86 /* class_inited */ FALSE, 87 /* initialize */ Initialize, 88 /* initialize_hook */ NULL, 89 /* realize */ Realize, 90 /* actions */ NULL, 91 /* num_actions */ 0, 92 /* resources */ resources, 93 /* resource_count */ XtNumber(resources), 94 /* xrm_class */ NULLQUARK, 95 /* compress_motion */ TRUE, 96 /* compress_exposure */ TRUE, 97 /* compress_enterleave */ TRUE, 98 /* visible_interest */ FALSE, 99 /* destroy */ Destroy, 100 /* resize */ Resize, 101 /* expose */ Redisplay, 102 /* set_values */ SetValues, 103 /* set_values_hook */ NULL, 104 /* set_values_almost */ XtInheritSetValuesAlmost, 105 /* get_values_hook */ NULL, 106 /* accept_focus */ NULL, 107 /* version */ XtVersion, 108 /* callback_private */ NULL, 109 /* tm_table */ NULL, 110 /* query_geometry */ XtInheritQueryGeometry, 111 /* display_accelerator */ XtInheritDisplayAccelerator, 112 /* extension */ NULL 113 }, 114 { /* simple fields */ 115 /* change_sensitive */ XtInheritChangeSensitive, 116 /* extension */ NULL 117 }, 118 { /* logo fields */ 119 /* ignore */ 0 120 } 121}; 122 123WidgetClass logoWidgetClass = (WidgetClass) &logoClassRec; 124 125 126/***************************************************************************** 127 * * 128 * private utility routines * 129 * * 130 *****************************************************************************/ 131 132static void 133create_gcs(LogoWidget w) 134{ 135 XGCValues v = { 0 }; 136 137#ifdef XRENDER 138 w->logo.fgpixel = w->logo.fg.pixel; 139#endif 140 141 v.foreground = w->logo.fgpixel; 142 w->logo.foreGC = XtGetGC ((Widget) w, GCForeground, &v); 143 v.foreground = w->core.background_pixel; 144 w->logo.backGC = XtGetGC ((Widget) w, GCForeground, &v); 145} 146 147static void 148check_shape(LogoWidget w) 149{ 150 if (w->logo.shape_window) { 151 int event_base, error_base; 152 153 if (!XShapeQueryExtension (XtDisplay (w), &event_base, &error_base)) 154 w->logo.shape_window = FALSE; 155 } 156} 157 158/* ARGSUSED */ 159static void 160unset_shape(LogoWidget w) 161{ 162 XSetWindowAttributes attr = { 0 }; 163 unsigned long mask; 164 Display *dpy = XtDisplay ((Widget) w); 165 Window win = XtWindow ((Widget) w); 166 167 if (w->core.background_pixmap != None && 168 w->core.background_pixmap != XtUnspecifiedPixmap) { 169 attr.background_pixmap = w->core.background_pixmap; 170 mask = CWBackPixmap; 171 } else { 172 attr.background_pixel = w->core.background_pixel; 173 mask = CWBackPixel; 174 } 175 XChangeWindowAttributes (dpy, win, mask, &attr); 176 XShapeCombineMask (dpy, win, ShapeBounding, 0, 0, None, ShapeSet); 177 if (!w->logo.foreGC) create_gcs (w); 178 w->logo.need_shaping = w->logo.shape_window; 179} 180 181static void 182set_shape(LogoWidget w) 183{ 184 GC ones, zeros; 185 Display *dpy = XtDisplay ((Widget) w); 186 Window win = XtWindow ((Widget) w); 187 unsigned int width = (unsigned int) w->core.width; 188 unsigned int height = (unsigned int) w->core.height; 189 Pixmap pm = XCreatePixmap (dpy, win, width, height, (unsigned int) 1); 190 XGCValues v = { 0 }; 191 192 v.foreground = (Pixel) 1; 193 v.background = (Pixel) 0; 194 ones = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v); 195 v.foreground = (Pixel) 0; 196 v.background = (Pixel) 1; 197 zeros = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v); 198 199 if (pm && ones && zeros) { 200 int x = 0, y = 0; 201 Widget parent; 202 203 XmuDrawLogo (dpy, pm, ones, zeros, 0, 0, width, height); 204 for (parent = (Widget) w; XtParent(parent); 205 parent = XtParent(parent)) { 206 x += parent->core.x + parent->core.border_width; 207 y += parent->core.y + parent->core.border_width; 208 } 209 XShapeCombineMask (dpy, XtWindow (parent), ShapeBounding, 210 x, y, pm, ShapeSet); 211 w->logo.need_shaping = FALSE; 212 } else { 213 unset_shape (w); 214 } 215 if (ones) XFreeGC (dpy, ones); 216 if (zeros) XFreeGC (dpy, zeros); 217 if (pm) XFreePixmap (dpy, pm); 218} 219 220 221/***************************************************************************** 222 * * 223 * class methods * 224 * * 225 *****************************************************************************/ 226 227#ifdef XRENDER 228 229static void 230RenderPrepare (LogoWidget w) 231{ 232 if (!w->logo.draw) 233 { 234 w->logo.draw = XftDrawCreate (XtDisplay (w), XtWindow (w), 235 DefaultVisual (XtDisplay (w), 236 DefaultScreen(XtDisplay (w))), 237 w->core.colormap); 238 } 239} 240 241static XtConvertArgRec xftColorConvertArgs[] = { 242 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 243 sizeof(Screen *)}, 244 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 245 sizeof(Colormap)} 246}; 247 248#define donestr(type, value, tstr) \ 249 do { \ 250 if (toVal->addr != NULL) { \ 251 if (toVal->size < sizeof(type)) { \ 252 toVal->size = sizeof(type); \ 253 XtDisplayStringConversionWarning(dpy, \ 254 (char*) fromVal->addr, tstr); \ 255 return False; \ 256 } \ 257 *(type*)(toVal->addr) = (value); \ 258 } \ 259 else { \ 260 static type static_val; \ 261 static_val = (value); \ 262 toVal->addr = (XPointer)&static_val; \ 263 } \ 264 toVal->size = sizeof(type); \ 265 return True; \ 266 } while (0) 267 268static void 269XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, 270 _X_UNUSED 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 _X_UNUSED 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 = (XRenderColor) { 325 .red = 0, 326 .green = 0, 327 .blue = 0, 328 .alpha = 0xffff 329 }; 330 } 331 else if (strcasecmp (spec, XtDefaultBackground) == 0) 332 { 333 renderColor = (XRenderColor) { 334 .red = 0xffff, 335 .green = 0xffff, 336 .blue = 0xffff, 337 .alpha = 0xffff 338 }; 339 } 340 else if (!XRenderParseColor (dpy, spec, &renderColor)) 341 return False; 342 if (!XftColorAllocValue (dpy, 343 DefaultVisual (dpy, 344 XScreenNumberOfScreen (screen)), 345 colormap, 346 &renderColor, 347 &xftColor)) 348 return False; 349 350 donestr (XftColor, xftColor, XtRXftColor); 351} 352 353 354#endif 355 356static void 357ClassInitialize(void) 358{ 359#ifdef XRENDER 360 XtSetTypeConverter (XtRString, XtRXftColor, 361 XmuCvtStringToXftColor, 362 xftColorConvertArgs, XtNumber(xftColorConvertArgs), 363 XtCacheByDisplay, XmuFreeXftColor); 364#endif 365} 366 367/* ARGSUSED */ 368static void 369Initialize(_X_UNUSED Widget request, Widget new, 370 _X_UNUSED ArgList args, _X_UNUSED Cardinal *num_args) 371{ 372 LogoWidget w = (LogoWidget)new; 373 374#ifdef XRENDER 375 w->logo.draw = NULL; 376 w->logo.fgpixel = w->logo.fg.pixel; 377#endif 378 if (w->core.width < 1) w->core.width = 100; 379 if (w->core.height < 1) w->core.height = 100; 380 381 w->logo.foreGC = (GC) NULL; 382 w->logo.backGC = (GC) NULL; 383 check_shape (w); 384 w->logo.need_shaping = w->logo.shape_window; 385} 386 387static void 388Destroy(Widget gw) 389{ 390 LogoWidget w = (LogoWidget) gw; 391 if (w->logo.foreGC) { 392 XtReleaseGC (gw, w->logo.foreGC); 393 w->logo.foreGC = (GC) NULL; 394 } 395 if (w->logo.backGC) { 396 XtReleaseGC (gw, w->logo.backGC); 397 w->logo.backGC = (GC) NULL; 398 } 399} 400 401static void 402Realize(Widget gw, XtValueMask *valuemaskp, XSetWindowAttributes *attr) 403{ 404 LogoWidget w = (LogoWidget) gw; 405 406 if (w->logo.shape_window) { 407 attr->background_pixel = w->logo.fgpixel; /* going to shape */ 408 *valuemaskp |= CWBackPixel; 409 } else 410 create_gcs (w); 411 (*logoWidgetClass->core_class.superclass->core_class.realize) 412 (gw, valuemaskp, attr); 413} 414 415static void 416Resize(Widget gw) 417{ 418 LogoWidget w = (LogoWidget) gw; 419 420 if (w->logo.shape_window && XtIsRealized(gw)) set_shape (w); 421} 422 423/* ARGSUSED */ 424static void 425Redisplay(Widget gw, _X_UNUSED XEvent *event, _X_UNUSED Region region) 426{ 427 LogoWidget w = (LogoWidget) gw; 428 429 if (w->logo.shape_window) { 430 if (w->logo.need_shaping) set_shape (w); /* may change shape flag */ 431 } 432 if (!w->logo.shape_window) { 433#ifdef XRENDER 434 if (w->logo.render) 435 { 436 RenderPrepare (w); 437 438 XClearWindow (XtDisplay(w), XtWindow(w)); 439 RenderLogo (XtDisplay(w), PictOpOver, 440 XftDrawSrcPicture (w->logo.draw, &w->logo.fg), 441 XftDrawPicture (w->logo.draw), 442 XRenderFindStandardFormat (XtDisplay (w), 443 w->logo.sharp ? 444 PictStandardA1: 445 PictStandardA8), 446 0, 0, (unsigned int) w->core.width, 447 (unsigned int) w->core.height); 448 } 449 else 450#endif 451 { 452 XmuDrawLogo (XtDisplay(w), XtWindow(w), w->logo.foreGC, w->logo.backGC, 453 0, 0, (unsigned int) w->core.width, 454 (unsigned int) w->core.height); 455 } 456 } 457} 458 459/* ARGSUSED */ 460static Boolean 461SetValues (Widget gcurrent, _X_UNUSED Widget grequest, Widget gnew, 462 _X_UNUSED ArgList args, _X_UNUSED Cardinal *num_args) 463{ 464 LogoWidget current = (LogoWidget) gcurrent; 465 LogoWidget new = (LogoWidget) gnew; 466 Boolean redisplay = FALSE; 467 468 if (new->logo.shape_window && 469 new->logo.shape_window != current->logo.shape_window) 470 check_shape (new); /* validate shape_window */ 471 472 if ((new->logo.fgpixel != current->logo.fgpixel) || 473 (new->core.background_pixel != current->core.background_pixel)) { 474 Destroy (gnew); 475 if (!new->logo.shape_window) create_gcs (new); 476 redisplay = TRUE; 477 } 478 479 if (new->logo.shape_window != current->logo.shape_window) { 480 if (new->logo.shape_window) { 481 Destroy (gnew); 482 if (XtIsRealized(gnew)) 483 set_shape (new); 484 else 485 new->logo.need_shaping = True; 486 redisplay = FALSE; 487 } else { 488 if (XtIsRealized(gnew)) 489 unset_shape (new); /* creates new GCs */ 490 redisplay = TRUE; 491 } 492 } 493 494 return (redisplay); 495} 496