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