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