1 #include <assert.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4
5 #include <X11/xpm.h>
6 #include <X11/Xmu/StdCmap.h>
7 #include <X11/Xmu/Atoms.h>
8
9 #include <Xm/Xm.h>
10 #include <Xm/Form.h>
11 #include <Xm/PushB.h>
12
13 // define to 0 for default visual - a visualid to get specific visual
14 #define WANT_VISUALID 0
15
16 static const char * home_xpm[] = {
17 "24 24 11 1",
18 " c None",
19 ". c #000000",
20 "+ c #808080",
21 "@ c #898989",
22 "# c #C0C0C0",
23 "$ c #F9F9F9",
24 "% c #424242",
25 "& c #A4A4A4",
26 "* c #5D5D5D",
27 "= c #C1C1C1",
28 "- c #DFDFDF",
29 " ", " ", " ",
30 " .. ", " .. ", " ............. ",
31 " ..+............ ", " ..+@+............ ", " ..+###+............ ",
32 " ..+#$$$#+............ ", " ...#$$$$$#+.......%% ", " .$+&$$$+++....%**% ",
33 " .$&#$$$+#$.*%**%+% ", " .$##$$$=#$$**++++% ", " .$$$$$$--$$++++%+% ",
34 " .$$$$$$$$$$+%++*+% ", " .$$$@@#-$$$+*++++% ", " .$$$@##-$$$+%+++%% ",
35 " .$$$###-$$$+++%% ", " .%+####-$$$+%% ", " %%%%%%%..% ",
36 " ", " ", " "
37 };
38
39
40 Pixmap
createPixmapFromXpm(Widget widget,const char ** xpm)41 createPixmapFromXpm(Widget widget, const char ** xpm)
42 {
43 Pixmap pixels = 0;
44 Widget shell = widget;
45 while (! XtIsShell(shell) && shell != (Widget) NULL) {
46 shell = XtParent(shell);
47 }
48 assert(shell != (Widget) NULL);
49 fprintf(stderr, "shell: %p\n", shell);
50 Display * display = XtDisplay(shell);
51
52 XpmAttributes attrs;
53 attrs.visual = NULL;
54 attrs.colormap = 0;
55 attrs.depth = 0;
56 attrs.valuemask = XpmVisual | XpmColormap | XpmDepth;
57
58 XtVaGetValues(shell, XmNcolormap, &attrs.colormap, NULL);
59 XtVaGetValues(shell, XmNdepth, &attrs.depth, NULL);
60 XtVaGetValues(shell, XmNvisual, &attrs.visual, NULL);
61 if ( attrs.visual == NULL ) {
62 fprintf(stderr, "attrs.visual for shell was NULL - using default\n");
63 attrs.visual = DefaultVisual(display, DefaultScreen(display));
64 attrs.depth = DefaultDepth(display, DefaultScreen(display));
65 attrs.colormap = DefaultColormap(display, DefaultScreen(display));
66 }
67
68 /* I'm questioning the use of the root Window here... */
69 /* An alternative approach could maybe be to set it up once the window was
70 * created (so we can use the actual window in question) through the use
71 * of XtAddCallback()? */
72
73 Drawable draw = RootWindow(display, DefaultScreen(display));
74 Pixmap stencil = 0;
75
76 // FIXME: that cast is pretty nasty -- get rid of it. 20020319 mortene.
77 int error = XpmCreatePixmapFromData(display, draw, (char **)xpm, &pixels, &stencil, &attrs);
78
79 if (error != XpmSuccess) {
80 fprintf(stderr, "XpmCreatePixmapFromData() failed: %d", error);
81 return (Pixmap) 0;
82 }
83
84 if (stencil) {
85 Pixel bg;
86 XtVaGetValues(widget, XmNbackground, &bg, NULL);
87
88 XImage * pixmap = XGetImage(display, pixels, 0, 0, attrs.width, attrs.height,
89 0xffffffff, ZPixmap);
90 XImage * mask = XGetImage(display, stencil, 0, 0, attrs.width, attrs.height,
91 0xffffffff, ZPixmap);
92 assert(pixmap != NULL && mask != NULL);
93
94 for (unsigned int x = 0; x < attrs.width; x++) {
95 for (unsigned int y = 0; y < attrs.height; y++) {
96 Pixel pixel = XGetPixel(mask, x, y);
97 Bool usebg = (pixel == 0);
98 if (usebg) { // background must be set in image
99 XPutPixel(pixmap, x, y, bg);
100 }
101 }
102 }
103
104 GC temp = XCreateGC(display, pixels, 0, NULL);
105 XPutImage(display, pixels, temp, pixmap,
106 0, 0, 0, 0, attrs.width, attrs.height);
107 XFreeGC(display, temp);
108
109 XDestroyImage(pixmap);
110 XDestroyImage(mask);
111 }
112 return pixels;
113 }
114
115 int
main(int argc,char ** argv)116 main(int argc, char ** argv)
117 {
118
119 setbuf(stdout, NULL);
120 setbuf(stderr, NULL);
121
122 Display * display = XOpenDisplay(NULL);
123 assert(display != NULL);
124 XSynchronize(display, True);
125
126 XtAppContext context = XtCreateApplicationContext();
127
128 Widget appshell = XtVaAppInitialize(&context, "SoXtTest", NULL, 0, &argc, argv, NULL, NULL);
129 fprintf(stderr, "appshell: %p\n", appshell);
130
131 #if WANT_VISUALID
132 int i, numvisuals;
133 unsigned int wanted = WANT_VISUALID;
134 XVisualInfo templ;
135 XVisualInfo * visuals = XGetVisualInfo(display, VisualNoMask, &templ, &numvisuals);
136 for ( i = 0; i < numvisuals; i++ ) {
137 if ( visuals[i].visualid == wanted ) goto selected;
138 }
139 assert(0 && "no visual selected");
140 selected:
141
142 Visual * visual = visuals[i].visual;
143 int visualid = visuals[i].visualid;
144 int depth = visuals[i].depth;
145 Colormap colormap = 0;
146
147 fprintf(stderr, "visualid: %d, depth: %d, class: %s\n", visualid, depth, visuals[i].c_class == DirectColor ? "DirectColor" : "Other");
148
149 int numcmaps;
150 XStandardColormap * stdcolormaps = NULL;
151 if ( XmuLookupStandardColormap(display, visuals[i].screen, visuals[i].visualid, visuals[i].depth,
152 XA_RGB_DEFAULT_MAP, False, True) &&
153 XGetRGBColormaps(display, RootWindow(display, visuals[i].screen),
154 &stdcolormaps, &numcmaps, XA_RGB_DEFAULT_MAP) ) {
155 for ( int j = 0; j < numcmaps; j++ ) {
156 if (stdcolormaps[j].visualid == visuals[i].visualid) {
157 colormap = stdcolormaps[j].colormap;
158 goto cont;
159 }
160 }
161 colormap = XCreateColormap(display, RootWindow(display, visuals[i].screen), visuals[i].visual, AllocNone);
162 fprintf(stderr, "standard RGB colormaps did not work with visual - created own (%ld)", colormap);
163 } else {
164 assert(0);
165 }
166
167 cont:
168 fprintf(stderr, "colormap: %ld\n", colormap);
169 #else
170 Visual * visual = NULL;
171 int depth = 0;
172 Colormap colormap = 0;
173
174 int snum = XDefaultScreen(display);
175 visual = XDefaultVisual(display, snum);
176 depth = XDefaultDepth(display, snum);
177 colormap = XDefaultColormap(display, snum);
178
179 fprintf(stderr, "visual: %p, depth: %d\n", visual, depth);
180 fprintf(stderr, "colormap: %ld\n", colormap);
181 #endif
182
183 XtVaSetValues(appshell,
184 XmNwidth, 100,
185 XmNheight, 100,
186 XmNvisual, visual,
187 XmNcolormap, colormap,
188 XmNdepth, depth,
189 NULL);
190
191 Widget form = XtVaCreateManagedWidget(
192 "form", xmFormWidgetClass,
193 appshell,
194 NULL);
195
196 Widget button = XtVaCreateManagedWidget(
197 "button", xmPushButtonWidgetClass,
198 form,
199 XmNtopAttachment, XmATTACH_FORM,
200 XmNleftAttachment, XmATTACH_FORM,
201 XmNbottomAttachment, XmATTACH_FORM,
202 XmNrightAttachment, XmATTACH_FORM,
203 NULL);
204
205 Pixmap pixmap = createPixmapFromXpm(button, home_xpm);
206 XtVaSetValues(button,
207 XmNlabelType, XmPIXMAP,
208 XmNlabelPixmap, pixmap,
209 XmNlabelInsensitivePixmap, pixmap,
210 XmNselectPixmap, pixmap,
211 XmNselectInsensitivePixmap, pixmap,
212 NULL);
213
214 Widget list[] = { appshell, form, button, NULL };
215 XtSetWMColormapWindows(appshell, list, 3);
216
217 XtRealizeWidget(appshell);
218 XtAppMainLoop(context);
219 }
220
221