1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22 */
23 #ifdef REV_INFO
24 #ifndef lint
25 static char rcsid[] = "$TOG: DrawingA.c /main/16 1999/10/13 16:16:41 mgreess $"
26 #endif
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 
34 #include <Xm/TransltnsP.h>
35 #include <Xm/VaSimpleP.h>
36 #include "DrawingAI.h"
37 #include "GadgetUtiI.h"
38 #include "GMUtilsI.h"
39 #include "RepTypeI.h"
40 #include "TraversalI.h"
41 #include "XmI.h"
42 
43 
44 #define	MARGIN_DEFAULT		10
45 
46 #define defaultTranslations	_XmDrawingA_defaultTranslations
47 #define traversalTranslations	_XmDrawingA_traversalTranslations
48 
49 
50 /********    Static Function Declarations    ********/
51 
52 static void ClassInitialize( void ) ;
53 static void ClassPartInitialize(
54                         WidgetClass w_class) ;
55 static void Initialize(
56                         Widget rw,
57                         Widget nw,
58                         ArgList args,
59                         Cardinal *num_args) ;
60 static void Redisplay(
61                         Widget wid,
62                         XEvent *event,
63                         Region region) ;
64 static void Resize(
65                         Widget wid) ;
66 static XtGeometryResult GeometryManager(
67                         Widget w,
68                         XtWidgetGeometry *request,
69                         XtWidgetGeometry *reply) ;
70 static void ChangeManaged(
71                         Widget wid) ;
72 static Boolean SetValues(
73                         Widget cw,
74                         Widget rw,
75                         Widget nw,
76                         ArgList args,
77                         Cardinal *num_args) ;
78 static XtGeometryResult QueryGeometry(
79                         Widget wid,
80                         XtWidgetGeometry *intended,
81                         XtWidgetGeometry *desired) ;
82 static XmNavigability WidgetNavigable(
83                         Widget wid) ;
84 
85 /********    End Static Function Declarations    ********/
86 
87 
88 static XtActionsRec actionsList[] =
89 {
90    { "DrawingAreaInput", _XmDrawingAreaInput },
91 };
92 
93 
94 /*  Resource definitions for DrawingArea
95  */
96 
97 static XtResource resources[] =
98 {
99     {	XmNmarginWidth,
100 	    XmCMarginWidth, XmRHorizontalDimension, sizeof (Dimension),
101 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_width),
102 	    XmRImmediate, (XtPointer) MARGIN_DEFAULT
103 	},
104 
105     {	XmNmarginHeight,
106 	    XmCMarginHeight, XmRVerticalDimension, sizeof (Dimension),
107 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_height),
108 	    XmRImmediate, (XtPointer) MARGIN_DEFAULT
109 	},
110 
111    {	XmNresizeCallback,
112 	    XmCCallback, XmRCallback, sizeof (XtCallbackList),
113 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.resize_callback),
114 	    XmRImmediate, (XtPointer) NULL
115 	},
116 
117    {	XmNexposeCallback,
118 	    XmCCallback, XmRCallback, sizeof (XtCallbackList),
119 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.expose_callback),
120 	    XmRImmediate, (XtPointer) NULL
121 	},
122 
123    {	XmNinputCallback,
124 	    XmCCallback, XmRCallback, sizeof (XtCallbackList),
125 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.input_callback),
126 	    XmRImmediate, (XtPointer) NULL
127 	},
128 #ifndef XM_PART_BC
129    {	XmNconvertCallback,
130 	    XmCCallback, XmRCallback, sizeof (XtCallbackList),
131 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.convert_callback),
132 	    XmRImmediate, (XtPointer) NULL
133 	},
134 
135    {	XmNdestinationCallback,
136 	    XmCCallback, XmRCallback, sizeof (XtCallbackList),
137 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.destination_callback),
138 	    XmRImmediate, (XtPointer) NULL
139 	},
140 #endif
141 
142 {	XmNresizePolicy,
143 	    XmCResizePolicy, XmRResizePolicy, sizeof (unsigned char),
144 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.resize_policy),
145 	    XmRImmediate, (XtPointer) XmRESIZE_ANY
146 	},
147 
148 };
149 
150 
151 static XmSyntheticResource syn_resources[] =
152 {
153    {	XmNmarginWidth,
154 	    sizeof (Dimension),
155 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_width),
156 	    XmeFromHorizontalPixels, XmeToHorizontalPixels
157 	},
158 
159    {	XmNmarginHeight,
160 	    sizeof (Dimension),
161 	    XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_height),
162 	    XmeFromVerticalPixels, XmeToVerticalPixels
163 	},
164 };
165 
166 
167 
168 /****************************************************************
169  *
170  * Full class record constant
171  *
172  ****************************************************************/
173 
174 static XmBaseClassExtRec baseClassExtRec = {
175     NULL,
176     NULLQUARK,
177     XmBaseClassExtVersion,
178     sizeof(XmBaseClassExtRec),
179     NULL,				/* InitializePrehook	*/
180     NULL,				/* SetValuesPrehook	*/
181     NULL,				/* InitializePosthook	*/
182     NULL,				/* SetValuesPosthook	*/
183     NULL,				/* secondaryObjectClass	*/
184     NULL,				/* secondaryCreate	*/
185     NULL,               		/* getSecRes data	*/
186     { 0 },      			/* fastSubclass flags	*/
187     NULL,				/* getValuesPrehook	*/
188     NULL,				/* getValuesPosthook	*/
189     NULL,                               /* classPartInitPrehook */
190     NULL,                               /* classPartInitPosthook*/
191     NULL,                               /* ext_resources        */
192     NULL,                               /* compiled_ext_resources*/
193     0,                                  /* num_ext_resources    */
194     FALSE,                              /* use_sub_resources    */
195     WidgetNavigable,                    /* widgetNavigable      */
196     NULL                                /* focusChange          */
197 };
198 
199 externaldef( xmdrawingareaclassrec) XmDrawingAreaClassRec
200                                    xmDrawingAreaClassRec =
201 {
202    {			/* core_class fields      */
203       (WidgetClass) &xmManagerClassRec,		/* superclass         */
204       "XmDrawingArea",				/* class_name         */
205       sizeof(XmDrawingAreaRec),			/* widget_size        */
206       ClassInitialize,	        		/* class_initialize   */
207       ClassPartInitialize,			/* class_part_init    */
208       FALSE,					/* class_inited       */
209       Initialize,      			        /* initialize         */
210       NULL,					/* initialize_hook    */
211       XtInheritRealize,				/* realize            */
212       actionsList,				/* actions	      */
213       XtNumber(actionsList),			/* num_actions	      */
214       resources,				/* resources          */
215       XtNumber(resources),			/* num_resources      */
216       NULLQUARK,				/* xrm_class          */
217       TRUE,					/* compress_motion    */
218       FALSE,					/* compress_exposure  */
219       TRUE,					/* compress_enterlv   */
220       FALSE,					/* visible_interest   */
221       NULL,			                /* destroy            */
222       Resize,           			/* resize             */
223       Redisplay,	        		/* expose             */
224       SetValues,                		/* set_values         */
225       NULL,					/* set_values_hook    */
226       XtInheritSetValuesAlmost,	        	/* set_values_almost  */
227       NULL,					/* get_values_hook    */
228       NULL,					/* accept_focus       */
229       XtVersion,				/* version            */
230       NULL,					/* callback_private   */
231       defaultTranslations,			/* tm_table           */
232       QueryGeometry,                    	/* query_geometry     */
233       NULL,             	                /* display_accelerator*/
234       (XtPointer)&baseClassExtRec,              /* extension          */
235    },
236    {		/* composite_class fields */
237       GeometryManager,    	                /* geometry_manager   */
238       ChangeManaged,	                	/* change_managed     */
239       XtInheritInsertChild,			/* insert_child       */
240       XtInheritDeleteChild,     		/* delete_child       */
241       NULL,                                     /* extension          */
242    },
243 
244    {		/* constraint_class fields */
245       NULL,					/* resource list        */
246       0,					/* num resources        */
247       sizeof(XmManagerConstraintRec),		/* constraint size      */
248       NULL,					/* init proc            */
249       NULL,					/* destroy proc         */
250       NULL,					/* set values proc      */
251       NULL,                                     /* extension            */
252    },
253 
254    {		/* manager_class fields */
255       traversalTranslations,			/* translations           */
256       syn_resources,				/* syn_resources      	  */
257       XtNumber (syn_resources),			/* num_get_resources 	  */
258       NULL,					/* syn_cont_resources     */
259       0,					/* num_get_cont_resources */
260       XmInheritParentProcess,                   /* parent_process         */
261       NULL,					/* extension           */
262    },
263 
264    {          /* drawingArea class */
265       (XtPointer) NULL,                         /* extension pointer */
266    }
267 };
268 
269 externaldef( xmdrawingareawidgetclass) WidgetClass xmDrawingAreaWidgetClass
270                                        = (WidgetClass) &xmDrawingAreaClassRec ;
271 
272 
273 
274 /****************************************************************/
275 static void
ClassInitialize(void)276 ClassInitialize( void )
277 {
278   baseClassExtRec.record_type = XmQmotif ;
279 }
280 
281 
282 /****************************************************************/
283 static void
ClassPartInitialize(WidgetClass w_class)284 ClassPartInitialize(
285         WidgetClass w_class )
286 {
287 
288     _XmFastSubclassInit( w_class, XmDRAWING_AREA_BIT) ;
289 
290 }
291 
292 
293 /****************************************************************
294  * Initialize. Check resizePolicy resource value
295  ****************/
296 /*ARGSUSED*/
297 static void
Initialize(Widget rw,Widget nw,ArgList args,Cardinal * num_args)298 Initialize(
299         Widget rw,		/* unused */
300         Widget nw,
301         ArgList args,		/* unused */
302         Cardinal *num_args )	/* unused */
303 {
304     XmDrawingAreaWidget new_w = (XmDrawingAreaWidget) nw ;
305 
306     if(new_w->drawing_area.resize_policy != XmRESIZE_SWINDOW
307        && !XmRepTypeValidValue(XmRID_RESIZE_POLICY,
308                             new_w->drawing_area.resize_policy,
309 			    (Widget) new_w)    ) {
310 	new_w->drawing_area.resize_policy = XmRESIZE_ANY ;
311     }
312 }
313 
314 
315 
316 /****************************************************************
317  * General redisplay function called on exposure events.
318  ****************/
319 static void
Redisplay(Widget wid,XEvent * event,Region region)320 Redisplay(
321         Widget wid,
322         XEvent *event,
323         Region region )
324 {
325     XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
326     XmDrawingAreaCallbackStruct cb;
327 /****************/
328 
329     cb.reason = XmCR_EXPOSE;
330     cb.event = event;
331     cb.window = XtWindow (da);
332 
333     XtCallCallbackList ((Widget) da, da->drawing_area.expose_callback, &cb);
334 
335     XmeRedisplayGadgets( (Widget) da, event, region);
336 }
337 
338 
339 /****************************************************************
340  * Invoke the application resize callbacks.
341  ****************/
342 static void
Resize(Widget wid)343 Resize(
344         Widget wid )
345 {
346     XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
347     XmDrawingAreaCallbackStruct cb;
348 
349     cb.reason = XmCR_RESIZE;
350     cb.event = NULL;
351     cb.window = XtWindow (da);
352 
353     XtCallCallbackList ((Widget) da, da->drawing_area.resize_callback, &cb);
354 }
355 
356 static Widget
ObjectAtPoint(Widget wid,Position x,Position y)357 ObjectAtPoint(
358         Widget wid,
359         Position  x,
360         Position  y )
361 {
362     CompositeWidget cw = (CompositeWidget) wid ;
363     register int i;
364     register Widget widget;
365 
366     i = cw->composite.num_children ;
367     while( i-- ) {
368 	widget = cw->composite.children[i];
369 
370 	/* do not care for gadget only for the DA input */
371 	if (XmIsGadget(widget) && XtIsManaged (widget)) {
372 	    if (x >= widget->core.x && y >= widget->core.y &&
373 		x < widget->core.x + widget->core.width    &&
374 		y < widget->core.y + widget->core.height)
375 		return (widget);
376 	}
377     }
378 
379     return (NULL);
380 }
381 
382 
383 /****************************************************************
384  * This function processes key and button presses and releases
385  *   belonging to the DrawingArea.
386  ****************/
387 /*ARGSUSED*/
388 void
_XmDrawingAreaInput(Widget wid,XEvent * event,String * params,Cardinal * num_params)389 _XmDrawingAreaInput(
390         Widget wid,
391         XEvent *event,
392         String *params,		/* unused */
393         Cardinal *num_params )	/* unused */
394 {
395     XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
396     XmDrawingAreaCallbackStruct cb ;
397     int x, y ;
398     Boolean button_event = True, input_on_gadget ;
399 
400     if ((event->type == ButtonPress) ||
401 	(event->type == ButtonRelease)) {
402 	x = event->xbutton.x ;
403 	y = event->xbutton.y ;
404     } else
405     if (event->type == MotionNotify) {
406 	x = event->xmotion.x ;
407 	y = event->xmotion.y ;
408     } else
409     if ((event->type == KeyPress) ||
410 	(event->type == KeyRelease)) {
411 	x = event->xkey.x ;
412 	y = event->xkey.y ;
413 	button_event = False ;
414     } else return ;
415 	    /* Unrecognized event (cannot determine x, y of pointer).*/
416 
417     input_on_gadget = (ObjectAtPoint((Widget)da, x, y) != NULL);
418 
419     if (!input_on_gadget && (!da->manager.active_child || button_event)) {
420 	cb.reason = XmCR_INPUT ;
421 	cb.event = event ;
422 	cb.window = XtWindow( da) ;
423 	XtCallCallbackList ((Widget) da,
424 			    da->drawing_area.input_callback, &cb) ;
425 
426     }
427 }
428 
429 
430 /****************************************************************/
431 static XtGeometryResult
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)432 GeometryManager(
433         Widget w,
434         XtWidgetGeometry *request,
435         XtWidgetGeometry *reply )
436 {
437             XmDrawingAreaWidget da;
438 /*            XtGeometryHandler manager ; */
439 /****************/
440 
441     da = (XmDrawingAreaWidget) w->core.parent;
442 
443     /* function shared with Bulletin Board */
444     return(_XmGMHandleGeometryManager((Widget)da, w, request, reply,
445                                     da->drawing_area.margin_width,
446                                     da->drawing_area.margin_height,
447                                     da->drawing_area.resize_policy,
448                                     True)); /* no overlap checking */
449 }
450 
451 /****************************************************************
452  * Re-layout children.
453  ****************/
454 static void
ChangeManaged(Widget wid)455 ChangeManaged(
456         Widget wid )
457 {
458     XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
459 
460     /* function shared with Bulletin Board */
461     _XmGMEnforceMargin((XmManagerWidget)da,
462                      da->drawing_area.margin_width,
463                      da->drawing_area.margin_height,
464                      False); /* use movewidget, not setvalue */
465 
466     /* The first time, reconfigure only if explicit size were not given */
467 
468     if (XtIsRealized((Widget)da) || (!XtWidth(da)) || (!XtHeight(da))) {
469 
470       /* function shared with Bulletin Board */
471       (void)_XmGMDoLayout((XmManagerWidget)da,
472                           da->drawing_area.margin_width,
473                           da->drawing_area.margin_height,
474                           da->drawing_area.resize_policy,
475                           False);  /* queryonly not specified */
476         }
477 
478     XmeNavigChangeManaged((Widget) da) ;
479 }
480 
481 /****************************************************************/
482 /*ARGSUSED*/
483 static Boolean
SetValues(Widget cw,Widget rw,Widget nw,ArgList args,Cardinal * num_args)484 SetValues(
485         Widget cw,
486         Widget rw,		/* unused */
487         Widget nw,
488         ArgList args,		/* unused */
489         Cardinal *num_args )	/* unused */
490 {
491     XmDrawingAreaWidget current = (XmDrawingAreaWidget) cw ;
492     XmDrawingAreaWidget new_w = (XmDrawingAreaWidget) nw ;
493 
494     if(new_w->drawing_area.resize_policy != XmRESIZE_SWINDOW
495        && !XmRepTypeValidValue(XmRID_RESIZE_POLICY,
496 			    new_w->drawing_area.resize_policy,
497 			    (Widget) new_w)  ) {
498 	new_w->drawing_area.resize_policy =
499 	    current->drawing_area.resize_policy ;
500     }
501 
502 
503     /* If new margins, re-enforce them using movewidget,
504        then update the width and height so that XtSetValues does
505        the geometry request */
506     if (XtIsRealized((Widget) new_w) &&
507 	(((new_w->drawing_area.margin_width !=
508 	  current->drawing_area.margin_width) ||
509 	 (new_w->drawing_area.margin_height !=
510 	  current->drawing_area.margin_height)))) {
511 
512 	/* move the child around if necessary */
513 	_XmGMEnforceMargin((XmManagerWidget)new_w,
514 			   new_w->drawing_area.margin_width,
515 			   new_w->drawing_area.margin_height,
516 			   False); /* use movewidget, no request */
517 	_XmGMCalcSize ((XmManagerWidget)new_w,
518 		       new_w->drawing_area.margin_width,
519 		       new_w->drawing_area.margin_height,
520 		       &new_w->core.width, &new_w->core.height);
521     }
522 
523     return( False) ;
524 }
525 
526 
527 /****************************************************************
528  * Handle query geometry requests
529  ****************/
530 static XtGeometryResult
QueryGeometry(Widget wid,XtWidgetGeometry * intended,XtWidgetGeometry * desired)531 QueryGeometry(
532         Widget wid,
533         XtWidgetGeometry *intended,
534         XtWidgetGeometry *desired )
535 {
536     XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
537 
538      /* function shared with Bulletin Board */
539      return(_XmGMHandleQueryGeometry(wid, intended, desired,
540                                    da->drawing_area.margin_width,
541                                    da->drawing_area.margin_height,
542                                    da->drawing_area.resize_policy));
543 }
544 
545 
546 /****************************************************************
547  * Xm private class method
548  ****************/
549 
550 
551 static XmNavigability
WidgetNavigable(Widget wid)552 WidgetNavigable(
553         Widget wid)
554 {
555   if(    XtIsSensitive(wid)
556      &&  ((XmManagerWidget) wid)->manager.traversal_on    )
557     {
558       XmNavigationType nav_type = ((XmManagerWidget) wid)
559 	                                            ->manager.navigation_type ;
560       Widget *children = ((XmManagerWidget) wid)->composite.children ;
561       unsigned idx = 0 ;
562 
563       /* If a Drawing Area has a navigable child, and initial focus
564 	 is either NULL or point to this child, allow navigation to it.
565        */
566         while(idx < ((XmManagerWidget) wid)->composite.num_children) {
567 	  if  (_XmGetNavigability(children[idx]) &&
568 	       ((((XmManagerWidget) wid)->manager.initial_focus == NULL) ||
569 		(((XmManagerWidget) wid)->manager.initial_focus ==
570 		                                          children[idx]))){
571 	      if(    (nav_type == XmSTICKY_TAB_GROUP)
572 		 ||  (nav_type == XmEXCLUSIVE_TAB_GROUP)
573 		 ||  (    (nav_type == XmTAB_GROUP)
574 		      &&  !_XmShellIsExclusive( wid))) {
575 		  return XmDESCENDANTS_TAB_NAVIGABLE ;
576 	      }
577 	      return XmDESCENDANTS_NAVIGABLE ;
578 	  }
579 	  ++idx ;
580       }
581 
582       /* else just return the DA itself */
583 
584       if(    (nav_type == XmSTICKY_TAB_GROUP)
585 	 ||  (nav_type == XmEXCLUSIVE_TAB_GROUP)
586 	 ||  (    (nav_type == XmTAB_GROUP)
587 	      &&  !_XmShellIsExclusive( wid))    )
588 	{
589 	  return XmTAB_NAVIGABLE ;
590 	}
591       return XmCONTROL_NAVIGABLE ;
592     }
593   return XmNOT_NAVIGABLE ;
594 }
595 
596 
597 
598 
599 /****************************************************************
600  * This function creates and returns a DrawingArea widget.
601  ****************/
602 Widget
XmCreateDrawingArea(Widget p,String name,ArgList args,Cardinal n)603 XmCreateDrawingArea(
604         Widget p,
605         String name,
606         ArgList args,
607         Cardinal n )
608 {
609 /****************/
610 
611     return( XtCreateWidget( name, xmDrawingAreaWidgetClass, p, args, n)) ;
612 }
613 
614 Widget
XmVaCreateDrawingArea(Widget parent,char * name,...)615 XmVaCreateDrawingArea(
616         Widget parent,
617         char *name,
618         ...)
619 {
620     register Widget w;
621     va_list var;
622     int count;
623 
624     Va_start(var,name);
625     count = XmeCountVaListSimple(var);
626     va_end(var);
627 
628 
629     Va_start(var, name);
630     w = XmeVLCreateWidget(name,
631                          xmDrawingAreaWidgetClass,
632                          parent, False,
633                          var, count);
634     va_end(var);
635     return w;
636 }
637 
638 Widget
XmVaCreateManagedDrawingArea(Widget parent,char * name,...)639 XmVaCreateManagedDrawingArea(
640         Widget parent,
641         char *name,
642         ...)
643 {
644     Widget w = NULL;
645     va_list var;
646     int count;
647 
648     Va_start(var, name);
649     count = XmeCountVaListSimple(var);
650     va_end(var);
651 
652     Va_start(var, name);
653     w = XmeVLCreateWidget(name,
654                          xmDrawingAreaWidgetClass,
655                          parent, True,
656                          var, count);
657     va_end(var);
658     return w;
659 }
660