Setting a private colormap on a DrawingArea - Motif

This is a discussion on Setting a private colormap on a DrawingArea - Motif ; Hi, I've been working on this problem for some time and have read the posting on this newsgroup. I've tried the solutions but to no avail - and it's driving me mad! For my application I need to be able ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: Setting a private colormap on a DrawingArea

  1. Setting a private colormap on a DrawingArea

    Hi,

    I've been working on this problem for some time and have read the
    posting on this newsgroup. I've tried the solutions but to no avail -
    and it's driving me mad!

    For my application I need to be able to create a private colormap (for
    the purpose of overlays). When I create a writable colormap and then
    create a DrawingArea widget with the colormap attribute set it seems
    that the default colormap is used. When I create the top-level shell
    with the private colormap the correct colours appear in the DrawingArea
    but unfortunately all of the other windows seem to use the private
    colours and are messed up.

    Here is my test program that recreates the problem (in Ada but the
    X/Motif API should look familiar).

    Any help would be much appreciated.

    with Xt.Intrinsic;
    with Xt.Composite;
    with Xt.StringDefs;
    with Xt.Shell;
    with Motif.XmStrDefs;
    with StdArg;
    with X;
    with X.Args;
    with X.Strings;
    with X.Xlib;
    with X.XUtil;
    with X.XResource;
    with Unchecked_Conversion;
    With System.Storage_Elements;
    with Text_IO;
    with Interfaces.C;
    with Motif.DrawingA;
    with Motif.Xm;
    with Motif.Xmstrdefs;
    with Test_Colours_Pkg;

    procedure Test_Colours is

    use type Xt.Intrinsic.XtGCMask;
    use type X.Unsigned_Int;
    use type X.Xlib.Status;
    use type X.Unsigned_Long;

    Shell, Canvas : Xt.Intrinsic.Widget;
    App : aliased Xt.Intrinsic.XtAppContext;

    ArgList : StdArg.ArgList := StdArg.Empty;

    GraphicsContext : X.Xlib.GC;
    Value_Mask : Xt.Intrinsic.XtGCMask := X.GCForeground +
    X.GCBackground;
    Values : aliased X.Xlib.XGCValues;

    Depth : X.signed_int := 8;

    function "&" is new StdArg.Concat(Xt.Intrinsic.Arg);
    function "&" is new Stdarg.Concat(Motif.Xm.XmString);
    function "&" is new Stdarg.Concat(X.Strings.Const_Charp);


    Pixmap : X.Pixmap;

    The_Arg : Xt.Intrinsic.ArgList := new Xt.Intrinsic.Arg;


    Local_Window : X.Drawable;
    Success : X.Xlib.Status;

    Visual_Info : aliased X.XUtil.XVisualInfo;
    Visual : X.Xlib.Visual_Access;

    Number_Of_Planes : X.Unsigned_Int := 1;
    Number_Of_Colours : X.Unsigned_Int := 20;

    Default_Colourmap, Colourmap : X.Colormap := 0;

    type Plane_mask_Type is array (1..Number_Of_Planes) of aliased
    X.unsigned_long;
    Plane_Masks : Plane_mask_Type := (others => 0);

    type Pixels_Type is array (1..Number_Of_Colours) of aliased
    X.Unsigned_Long;
    Border_Pixels, Pixels : Pixels_Type := (others => 0);
    Colour_Definitions : Pixels_Type := (others => 0);

    Display : X.Xlib.XDisplay_Access := null;
    Screen : X.Signed_Int := 0;

    Windows : array (1..2) of aliased X.Window;

    App_Name : aliased Interfaces.C.Char_Array :=
    Interfaces.C.To_C("X");
    App_Class : aliased Interfaces.C.Char_Array :=
    Interfaces.C.To_C("XTest");
    Options_List: X.XResource.XrmOptionDescList;
    Zero : X.Int_Access := new X.Signed_Int'(0);

    begin
    Xt.Intrinsic.XtToolkitInitialize;

    App := Xt.Intrinsic.XtCreateApplicationContext;

    Display := Xt.Intrinsic.XtOpenDisplay
    (APP_CONTEXT => App,
    DISPLAY_STRING => Interfaces.C.To_C(""),
    APPLICATION_NAME => App_Name,
    APPLICATION_CLASS => App_Class,
    OPTIONS => OPTIONS_LIST,
    Num_Options => 0,
    ARGC => Zero,
    ARGV => Null);

    Success := X.XUtil.XMatchVisualInfo
    (Display => Display,
    Screen => X.Xlib.DefaultScreen(Display),
    Depth => Depth,
    Class => X.PseudoColor,
    Vinfo_Return => Visual_Info'access);

    if Success = X.Xlib.True then
    Text_IO.Put_Line ("Visual matched at a depth of " &
    X.Signed_Int'image(Depth));
    else
    Text_IO.Put_Line ("Visual not matched!");
    end if;

    Default_Colourmap :=
    X.XLib.XDefaultColormapOfScreen(X.Xlib.DefaultScre enOfDisplay(Display));

    Colourmap := X.Xlib.XCopyColormapandFree(Display => Display,

    Colormap => Default_Colourmap);
    Visual := Visual_Info.Visual;

    ArgList := ArgList & Xt.Intrinsic.Arg'(Name =>
    X.Strings.Charp(Motif.XmStrDefs.XmNvisual),
    Value =>
    Visual.all'address);


    -- Now create the top-level shell with the matched Visual
    Shell := Xt.Intrinsic.XtVaAppCreateShell
    (application_name =>
    X.Strings.To_Charp(App_Name'access),
    application_class =>
    X.Strings.To_Charp(App_Class'access),
    widget_class =>
    Xt.Shell.applicationShellWidgetClass_obj,
    display => Display,
    Args => ArgList);


    Success := X.XLib.XAllocColorCells
    (Display => Xt.Intrinsic.XtDisplay(Shell),
    Colormap => Colourmap,
    Contig => X.Xlib.True,
    Plane_Masks_Return => Plane_Masks(1)'access,
    nPlanes => 0,--Number_Of_planes,
    Pixels_Return => Pixels(1)'access,
    nPixels => Number_Of_Colours); -- Cells = nPixels *
    2 ** nPlanes = 4 cells

    if Success = X.Xlib.True then
    Text_IO.Put_Line ("Allocated colour cells" );
    else
    Text_IO.Put_Line ("No cells allocated");
    Pixels := (1 => 0,
    2 => 1,
    3 => 2,
    4 => 3,
    others => 10);
    end if;
    -- Create white
    Test_Colours_Pkg.Exact_Definitions(1) := (Red => 0,
    Green => 0,
    Blue => 0,
    Pixel => Pixels(1),
    Pad => 0,
    Flags =>
    Interfaces.C.Signed_Char(X.DoRed + X.DoGreen + X.DoBlue));

    X.Xlib.XStoreColor(Display => Xt.Intrinsic.XtDisplay(Shell),
    Colormap => Colourmap,
    Color =>
    Test_Colours_Pkg.Exact_Definitions(1)'access);

    -- Create bright red
    Test_Colours_Pkg.Exact_Definitions(2) := (Red => 16#FFFF#,
    Green => 0,
    Blue => 0,
    Pixel => Pixels(2),
    Pad => 0,
    Flags =>
    Interfaces.C.Signed_Char(X.DoRed + X.DoGreen + X.DoBlue));

    X.Xlib.XStoreColor(Display => Xt.Intrinsic.XtDisplay(Shell),
    Colormap => Colourmap,
    Color =>
    Test_Colours_Pkg.Exact_Definitions(2)'access);

    ArgList := StdArg.Empty;

    ArgList := ArgList & Xt.Intrinsic.Arg'(Name =>
    X.Strings.Charp(Motif.XmStrDefs.XmNvisual),
    Value => Visual.all'address);

    -- Set the Colormap attribute
    ArgList := ArgList & Xt.Intrinsic.Arg'(Name =>
    X.Strings.Charp(Motif.XmStrdefs.XmNColormap),
    Value =>
    System.Storage_Elements.To_Address(System.Storage_ Elements.Integer_Address(Colourmap)));

    Canvas := Xt.Intrinsic.XtVaCreateManagedWidget (Name =>
    "canvas",
    Widget_Class =>
    Motif.DrawingA.xmDrawingAreaWidgetClass_obj,
    parent =>
    Shell,
    args =>
    ArgList);

    Xt.Intrinsic.XtAddCallback(Widget => Canvas,
    Callback_Name =>
    Motif.xmstrdefs.XmNexposeCallback,
    Callback =>
    Test_Colours_Pkg.Redraw'access,
    Closure => null);

    Local_Window :=
    X.Drawable(X.Xlib.XRootWindowOfScreen(Xt.Intrinsic .XtScreen(Canvas)));

    GraphicsContext := X.XLib.XCreateGC (Display =>
    Xt.Intrinsic.XtDisplay(Canvas),
    D => Local_Window,
    ValueMask => 0,
    Values => Values'access);

    Pixmap := X.Xlib.XCreatePixmap (Display =>
    Xt.Intrinsic.XtDisplay(Canvas),
    D => Local_Window,
    Width => Test_Colours_Pkg.Width,
    Height => Test_Colours_Pkg.Height,
    Depth => X.Unsigned_Int(Depth));


    X.XLib.XSetForeground (Display => Xt.Intrinsic.XtDisplay(Canvas),
    GC => GraphicsContext,
    Foreground =>
    X.Xlib.BlackPixel(Xt.Intrinsic.XtDisplay(Shell), 0));

    X.Xlib.XFillRectangle (Display => Xt.Intrinsic.XtDisplay(Canvas),
    D => X.Drawable(Pixmap),
    GC => GraphicsContext,
    Xx => 0,
    Y => 0,
    Width => Test_Colours_Pkg.Width,
    Height => Test_Colours_Pkg.Height);


    Test_Colours_Pkg.GraphicsContext := GraphicsContext;
    Test_Colours_Pkg.Pixmap := Pixmap;

    Xt.Intrinsic.XtRealizeWidget(Shell);

    Windows (1) := Xt.Intrinsic.XtWindow(Canvas);
    Windows (2) := Xt.Intrinsic.XtWindow(Shell);

    Success := X.XLib.XSetWMColormapWindows(Display =>
    Xt.Intrinsic.XtDisplay(Shell),
    W =>
    Xt.Intrinsic.XtWindow(Shell),
    Colormap_Windows =>
    Windows(1)'access,
    Count => 2);

    if Success = X.Xlib.True then
    Text_IO.Put_Line ("WM Colormap Windows set" );
    else
    Text_IO.Put_Line ("Can't set WM Colormap Windows");
    end if;

    Xt.Intrinsic.XtAppMainLoop(App);

    end Test_Colours;

    Regards,

    Andy Bissell


  2. Re: Setting a private colormap on a DrawingArea


    On 9 Feb 2006, andy.bissell@objektum.com wrote:

    > For my application I need to be able to create a private colormap
    > (for the purpose of overlays). When I create a writable colormap and
    > then create a DrawingArea widget with the colormap attribute set it
    > seems that the default colormap is used. When I create the top-level
    > shell with the private colormap the correct colours appear in the
    > DrawingArea but unfortunately all of the other windows seem to use
    > the private colours and are messed up.


    > Here is my test program that recreates the problem (in Ada but the
    > X/Motif API should look familiar).


    It is a little difficult for me to understand the Ada. However, I
    have just looked into the issue recently. One problem I had with the
    private color map in the main app, several OEM widgets would throw
    fits. I only used the popup window for the private colormap.

    I didn't see if you explicitly requested a visual type anywhere in the
    Ada. Ie, did you want true color, pseudo, gray scale, etc. Have you
    looked at the visuals available from the X-server you are using? Keep
    in mind that different X-servers may provide a different list of
    visuals. Opps, I just re-read and it looks like an 8-bit pseudo.

    It looks like you are asking for 20 contiguous colors. Do you need
    them to be contiguous? The contiguous allocation is only relevant for
    a pseudo color mapping afaiu. There may be trouble trying to fit 20
    contiguous colors in the default visuals colormap.

    One things that wasn't apparent to me was the XStoreColors needs to
    have the pixel index set. I think you are using an array to get these
    value. This "pixel" is a logical index into the pseudo-color pallete.
    It is the number in a pixmap that will transform to the true color
    value. I never got this spelled out to me anywhere. You really only
    need contiguous values if you are using some private range. For
    example, I was using 6-bits of gray-scale in an 8-bit visual. I
    needed the colors to be contiguous as it is easy to convert from a
    "true color" gray scale to the contiguous range in the private color
    map. However, if your colors have no relation (ie, you won't use math
    to find a value), you probably don't need a contiguous range. Maybe
    to be clear. To convert from a 16-bit gray scale to the 6-bit would
    be like this,

    pseudo_index = (real_gray + 512) / 1024 + zero_pix; /* OR */
    pseudo_index = ((real_gray + (1 << 9)) >> 10) + zero_pix;

    zero_pix is the pixel[0] returned from XAllocColorCells for the
    continuous range. But maybe this isn't your problem (using
    contiguous)?

    Have you tried using "XtNColorMap" with your app shell, to give it the
    private color map and then populate this with your other widgets?
    They may have requested new colors that weren't in the
    XCopyColormapAndFree() originally [before everything gets created].

    I think if you use different color maps in child widgets, the parent
    has to have some color map focusing functionality (callback?).

    hth,
    Bill Pringlemeir.

    --
    Paradigm is a word too often used by those who would like to have a
    new idea but cannot think of one. - Mervyn King

  3. Re: Setting a private colormap on a DrawingArea

    Hi Bill,

    Thanks for your reply. You are quite right that the Ada app requests an
    8-bit pseudo visual. However, on the original platform (DECAlpha) the
    default colormap seems to be writable and this is where it all goes
    wrong for me!

    To be able to allocate private colours (for use in overlays) I have to
    create my own colormap, this I can do either in a contiguous or
    non-contiguous fashion. If I create the child DrawingArea widget with
    my private colormap the colours appear correctly within the DrawingArea
    but the other windows exhibit strange colours on the border
    decorations, mouse, etc, probably because they use the private colormap
    as well.

    I suppose I only have two options for solving this problem: 1) try and
    get 2 colormaps installed concurrently or 2) create a colormap that
    holds all of my private (overlay) colours and the colours used by the
    decorations, mouse, etc - then I need a way to force the windows to use
    these colours......

    Regards,

    Andy


  4. Re: Setting a private colormap on a DrawingArea


    wrote in message
    news:1139569698.167716.264360@o13g2000cwo.googlegr oups.com...
    > Hi Bill,
    >
    > Thanks for your reply. You are quite right that the Ada app requests an
    > 8-bit pseudo visual. However, on the original platform (DECAlpha) the
    > default colormap seems to be writable and this is where it all goes
    > wrong for me!
    >
    > To be able to allocate private colours (for use in overlays) I have to
    > create my own colormap, this I can do either in a contiguous or
    > non-contiguous fashion. If I create the child DrawingArea widget with
    > my private colormap the colours appear correctly within the DrawingArea
    > but the other windows exhibit strange colours on the border
    > decorations, mouse, etc, probably because they use the private colormap
    > as well.
    >
    > I suppose I only have two options for solving this problem: 1) try and
    > get 2 colormaps installed concurrently or 2) create a colormap that
    > holds all of my private (overlay) colours and the colours used by the
    > decorations, mouse, etc - then I need a way to force the windows to use
    > these colours......
    >
    > Regards,
    >
    > Andy
    >

    Most Unix platforms can only have use one colormap at a time. When you
    specify your private colormap, and your window has the focus, that colormap
    is used by all apps - and their colors may be very strange indeed. If you
    move focus to one of those apps, their colormap (probably the default
    colormap) gets used, and your app may look strange.

    If you need n specific colors, allocate your private colormap, then get the
    default colormap and copy it into yours. Then change the 20 you need, so
    only thosse 20 pixel values differ from the default map. Try to use pixel
    values near the upper end of the range - most window managers stick to the
    lower numbers for their default colors (for example, the pixel 1 (one) is
    often used as the color of the standard cursor). By selecting your pixel
    range jusiciously you can minimize your affect on other windows.

    --
    Fred L. Kleinschmidt
    Boeing Associate Technical Fellow
    Technical Architect, Software Reuse Project



  5. Re: Setting a private colormap on a DrawingArea

    In article <1139569698.167716.264360@o13g2000cwo.googlegroups. com> andy.bissell@objektum.com writes:

    >I suppose I only have two options for solving this problem: 1) try and
    >get 2 colormaps installed concurrently or 2) create a colormap that
    >holds all of my private (overlay) colours and the colours used by the
    >decorations, mouse, etc - then I need a way to force the windows to use
    >these colours......


    I'm not aware of any display hardware that can display two PseudoColor
    colormaps concurrently (except possible for some old SGI workstations that may
    have had this capability).

    Usually what you are trying will only work if the root visual and the visual
    for all the other elements is a TrueColor visual, the visual for your overlay
    is PseudoColor, and your display supports simultaneous 24-bit and 8-bit
    visuals (requires both the correct hardware and the correct graphics driver
    and an Xserver that supports this).

    Most Unix systems with high-end graphics cards can do this. Linux is
    trickier.

    -Pete Zakel
    (phz@seeheader.nospam)

    "In December [1994] Jack Horkheimer, who is host of a public television
    astronomy show and who ends each show urging viewers to `keep looking up'
    at the stars, broke four toes in his left foot when he stumbled on a deck
    one night while watching the star Canopus."

    -News Of The Weird by Chuck Shepherd

  6. Re: Setting a private colormap on a DrawingArea

    Hi Fred,

    Thanks for your reply. I think the best option as you point out is to
    use just one colormap with all of the appropriate colours installed
    from the defualt colormap. In my real application I use overlays to
    avoid redrawing the whole graphics area. I allocate 10 colours across 4
    planes resulting in 10 * 2**4 = 160 colour cells being allocated. You
    mention selecting the upper range pixels for the private colours but I
    can't see how you can specify the pixel indexes that are returned from
    the XAllocColorCells call, am I missing something or should I be using
    another mechanism to do this?

    Thanks,

    Andy


  7. Re: Setting a private colormap on a DrawingArea


    wrote in message
    news:1139830652.705623.320510@g47g2000cwa.googlegr oups.com...
    > Hi Fred,
    >
    > Thanks for your reply. I think the best option as you point out is to
    > use just one colormap with all of the appropriate colours installed
    > from the defualt colormap. In my real application I use overlays to
    > avoid redrawing the whole graphics area. I allocate 10 colours across 4
    > planes resulting in 10 * 2**4 = 160 colour cells being allocated. You
    > mention selecting the upper range pixels for the private colours but I
    > can't see how you can specify the pixel indexes that are returned from
    > the XAllocColorCells call, am I missing something or should I be using
    > another mechanism to do this?
    >
    > Thanks,
    >
    > Andy
    >

    If you have created your own private colormap, you do not need to call
    XAllocColorCells to get writable cells - you already have all of the cells,
    and all are writable (as long as you specified AllocAll when calling
    XCreateColormap). However, you still have to be careful to ensure that the
    pixel values you use for the overlay planes are correctly contiguous - or at
    least differ by toggling one bit.
    --
    Fred L. Kleinschmidt
    Boeing Associate Technical Fellow
    Technical Architect, Software Reuse Project



+ Reply to Thread