1 /*
   2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifndef HEADLESS
  27 
  28 #include <X11/IntrinsicP.h>
  29 #include "VDrawingAreaP.h"
  30 
  31 #endif /* !HEADLESS */
  32 
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 
  36 #ifdef __linux__
  37 /* XXX: Shouldn't be necessary. */
  38 #include "awt_p.h"
  39 #endif /* __linux__ */
  40 
  41 
  42 /******************************************************************
  43  *
  44  * Provides Canvas widget which allows the X11 visual to be
  45  * changed (the Motif DrawingArea restricts the visual to that
  46  * of the parent widget).
  47  *
  48  ******************************************************************/
  49 
  50 
  51 /******************************************************************
  52  *
  53  * VDrawingArea Widget Resources
  54  *
  55  ******************************************************************/
  56 
  57 #ifndef HEADLESS
  58 #define Offset(x)       (XtOffsetOf(VDrawingAreaRec, x))
  59 static XtResource resources[]=
  60 {
  61         { XtNvisual, XtCVisual, XtRVisual, sizeof(Visual*),
  62           Offset(vdrawing_area.visual), XtRImmediate, CopyFromParent}
  63 };
  64 
  65 
  66 static void Realize();
  67 static Boolean SetValues();
  68 static void Destroy ();
  69 
  70 static XmBaseClassExtRec baseClassExtRec = {
  71     NULL,
  72     NULLQUARK,
  73     XmBaseClassExtVersion,
  74     sizeof(XmBaseClassExtRec),
  75     NULL,                               /* InitializePrehook    */
  76     NULL,                               /* SetValuesPrehook     */
  77     NULL,                               /* InitializePosthook   */
  78     NULL,                               /* SetValuesPosthook    */
  79     NULL,                               /* secondaryObjectClass */
  80     NULL,                               /* secondaryCreate      */
  81     NULL,                               /* getSecRes data       */
  82     { 0 },                              /* fastSubclass flags   */
  83     NULL,                               /* getValuesPrehook     */
  84     NULL,                               /* getValuesPosthook    */
  85     NULL,                               /* classPartInitPrehook */
  86     NULL,                               /* classPartInitPosthook*/
  87     NULL,                               /* ext_resources        */
  88     NULL,                               /* compiled_ext_resources*/
  89     0,                                  /* num_ext_resources    */
  90     FALSE,                              /* use_sub_resources    */
  91     NULL,                               /* widgetNavigable      */
  92     NULL,                               /* focusChange          */
  93     NULL                                /* wrapper_data         */
  94 };
  95 
  96 VDrawingAreaClassRec vDrawingAreaClassRec = {
  97 {
  98     /* Core class part */
  99 
 100     /* superclass         */    (WidgetClass)&xmDrawingAreaClassRec,
 101     /* class_name         */    "VDrawingArea",
 102     /* widget_size        */    sizeof(VDrawingAreaRec),
 103     /* class_initialize   */    NULL,
 104     /* class_part_initialize*/  NULL,
 105     /* class_inited       */    FALSE,
 106     /* initialize         */    NULL,
 107     /* initialize_hook    */    NULL,
 108     /* realize            */    Realize,
 109     /* actions            */    NULL,
 110     /* num_actions        */    0,
 111     /* resources          */    resources,
 112     /* num_resources      */    XtNumber(resources),
 113     /* xrm_class          */    NULLQUARK,
 114     /* compress_motion    */    FALSE,
 115     /* compress_exposure  */    FALSE,
 116     /* compress_enterleave*/    FALSE,
 117     /* visible_interest   */    FALSE,
 118     /* destroy            */    Destroy,
 119     /* resize             */    XtInheritResize,
 120     /* expose             */    XtInheritExpose,
 121     /* set_values         */    SetValues,
 122     /* set_values_hook    */    NULL,
 123     /* set_values_almost  */    XtInheritSetValuesAlmost,
 124     /* get_values_hook    */    NULL,
 125     /* accept_focus       */    NULL,
 126     /* version            */    XtVersion,
 127     /* callback_offsets   */    NULL,
 128     /* tm_table           */    NULL,
 129     /* query_geometry       */  NULL,
 130     /* display_accelerator  */  NULL,
 131     /* extension            */  NULL
 132   },
 133 
 134    {            /* composite_class fields */
 135       XtInheritGeometryManager,                 /* geometry_manager   */
 136       XtInheritChangeManaged,                   /* change_managed     */
 137       XtInheritInsertChild,                     /* insert_child       */
 138       XtInheritDeleteChild,                     /* delete_child       */
 139       NULL,                                     /* extension          */
 140    },
 141 
 142    {            /* constraint_class fields */
 143       NULL,                                     /* resource list        */
 144       0,                                        /* num resources        */
 145       0,                                        /* constraint size      */
 146       NULL,                                     /* init proc            */
 147       NULL,                                     /* destroy proc         */
 148       NULL,                                     /* set values proc      */
 149       NULL,                                     /* extension            */
 150    },
 151 
 152    {            /* manager_class fields */
 153       XtInheritTranslations,                    /* translations           */
 154       NULL,                                     /* syn_resources          */
 155       0,                                        /* num_get_resources      */
 156       NULL,                                     /* syn_cont_resources     */
 157       0,                                        /* num_get_cont_resources */
 158       XmInheritParentProcess,                   /* parent_process         */
 159       NULL,                                     /* extension           */
 160    },
 161 
 162    {            /* drawingArea class */
 163            /* extension */      NULL
 164    },
 165 
 166    /* VDrawingArea class part */
 167    {
 168         /* extension    */      NULL
 169    }
 170 };
 171 
 172 WidgetClass vDrawingAreaClass = (WidgetClass)&vDrawingAreaClassRec;
 173 
 174 static Boolean
 175 SetValues(cw, rw, nw, args, num_args)
 176     Widget cw;
 177     Widget rw;
 178     Widget nw;
 179     ArgList args;
 180     Cardinal *num_args;
 181 {
 182     VDrawingAreaWidget current = (VDrawingAreaWidget)cw;
 183     VDrawingAreaWidget new_w = (VDrawingAreaWidget)nw;
 184 
 185     if (new_w->vdrawing_area.visual != current->vdrawing_area.visual) {
 186         new_w->vdrawing_area.visual = current->vdrawing_area.visual;
 187 #ifdef DEBUG
 188         fprintf(stdout, "VDrawingArea.SetValues: can't change visual from: visualID=%ld to visualID=%ld\n",
 189                      current->vdrawing_area.visual->visualid,
 190                      new_w->vdrawing_area.visual->visualid);
 191 #endif
 192 
 193     }
 194 
 195     return (False);
 196 }
 197 
 198 int
 199 FindWindowInList (Window parentWindow, Window *colormap_windows, int count)
 200 {
 201     int i;
 202 
 203     for (i = 0; i < count; i++)
 204         if (colormap_windows [i] == parentWindow)
 205            return i;
 206     return -1;
 207 }
 208 
 209 static void
 210 Realize(w, value_mask, attributes)
 211     Widget               w;
 212     XtValueMask          *value_mask;
 213     XSetWindowAttributes *attributes;
 214 {
 215     Widget parent;
 216     Status status;
 217     Window *colormap_windows;
 218     Window *new_colormap_windows;
 219     int count;
 220     int i;
 221     VDrawingAreaWidget vd = (VDrawingAreaWidget)w;
 222 
 223 #ifdef DEBUG
 224     fprintf(stdout, "VDrawingArea.Realize: visualID=%ld, depth=%d\n",
 225                         vd->vdrawing_area.visual->visualid, w->core.depth);
 226 #endif
 227 
 228     /* 4328588:
 229      * Since we have our own Realize() function, we don't execute the one for
 230      * our super-super class, XmManager, and miss the code which checks that
 231      * height and width != 0.  I've added that here.  -bchristi
 232      */
 233     if (!XtWidth(w)) XtWidth(w) = 1 ;
 234     if (!XtHeight(w)) XtHeight(w) = 1 ;
 235 
 236     w->core.window = XCreateWindow (XtDisplay (w), XtWindow (w->core.parent),
 237                         w->core.x, w->core.y, w->core.width, w->core.height,
 238                         0, w->core.depth, InputOutput,
 239                         vd->vdrawing_area.visual,
 240                         *value_mask, attributes );
 241 
 242     /* Need to add this window to the list of Colormap windows */
 243     parent = XtParent (w);
 244     while ((parent != NULL) && (!(XtIsShell (parent))))
 245         parent = XtParent (parent);
 246     if (parent == NULL) {
 247         fprintf (stderr, "NO TopLevel widget?!\n");
 248         return;
 249     }
 250 
 251     status = XGetWMColormapWindows (XtDisplay (w), XtWindow (parent),
 252                                     &colormap_windows, &count);
 253 
 254     /* If status is zero, add this window and shell to the list
 255        of colormap Windows */
 256     if (status == 0) {
 257         new_colormap_windows = (Window *) calloc (2, sizeof (Window));
 258         new_colormap_windows [0] = XtWindow (w);
 259         new_colormap_windows [1] = XtWindow (parent);
 260         XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
 261                                new_colormap_windows, 2);
 262         free (new_colormap_windows);
 263     } else {
 264         /* Check if parent is already in the list */
 265         int parent_entry = -1;
 266 
 267         if (count > 0)
 268             parent_entry = FindWindowInList (XtWindow (parent),
 269                                         colormap_windows, count);
 270         if (parent_entry == -1) {  /*  Parent not in list  */
 271             new_colormap_windows = (Window *) calloc (count + 2,
 272                                                 sizeof (Window));
 273             new_colormap_windows [0] = XtWindow (w);
 274             new_colormap_windows [1] = XtWindow (parent);
 275             for (i = 0; i < count; i++)
 276                 new_colormap_windows [i + 2] = colormap_windows [i];
 277             XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
 278                                    new_colormap_windows, count + 2);
 279 
 280         } else {        /* parent already in list, just add new window */
 281             new_colormap_windows = (Window *) calloc (count + 1,
 282                                                 sizeof (Window));
 283             new_colormap_windows [0] = XtWindow (w);
 284             for (i = 0; i < count; i++)
 285                 new_colormap_windows [i + 1] = colormap_windows [i];
 286             XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
 287                                    new_colormap_windows, count + 1);
 288         }
 289         free (new_colormap_windows);
 290         XFree (colormap_windows);
 291     }
 292 
 293 
 294 }
 295 
 296 static void
 297 Destroy(Widget widget)
 298 {
 299     Status status;
 300     Widget parent;
 301     Window *colormap_windows;
 302     Window *new_colormap_windows;
 303     int count;
 304     int listEntry;
 305     int i;
 306     int j;
 307 
 308     /* Need to get this window's parent shell first */
 309     parent = XtParent (widget);
 310     while ((parent != NULL) && (!(XtIsShell (parent))))
 311         parent = XtParent (parent);
 312     if (parent == NULL) {
 313         fprintf (stderr, "NO TopLevel widget?!\n");
 314         return;
 315     }
 316 
 317     status = XGetWMColormapWindows (XtDisplay (widget), XtWindow (parent),
 318                                     &colormap_windows, &count);
 319 
 320     /* If status is zero, then there were no colormap windows for
 321        the parent ?? */
 322 
 323     if (status == 0)
 324         return;
 325 
 326     /* Remove this window from the list of colormap windows */
 327     listEntry = FindWindowInList (XtWindow (widget), colormap_windows,
 328                                   count);
 329 
 330     new_colormap_windows = (Window *) calloc (count - 1, sizeof (Window));
 331     j = 0;
 332     for (i = 0; i < count; i++) {
 333         if (i == listEntry)
 334            continue;
 335         new_colormap_windows [j] = colormap_windows [i];
 336         j++;
 337     }
 338     XSetWMColormapWindows (XtDisplay (widget), XtWindow (parent),
 339                            new_colormap_windows, count - 1);
 340     free (new_colormap_windows);
 341     XFree (colormap_windows);
 342 
 343 }
 344 #endif /* !HEADLESS */