1 /* |
|
2 * Copyright 2000-2001 Sun Microsystems, Inc. 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. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 #if MOTIF_VERSION!=1 |
|
27 #error This file should only be compiled with motif 1.2 |
|
28 #endif |
|
29 |
|
30 #include "awt_motif.h" |
|
31 #include <Xm/VendorSEP.h> |
|
32 #include <Xm/DragCP.h> |
|
33 #include "debug_util.h" |
|
34 #include "awt.h" |
|
35 |
|
36 /* |
|
37 * awt_motif_getIMStatusHeight is a cut and paste of the ImGetGeo() function |
|
38 * found in CDE Motif's Xm/XmIm.c. It returns the height of the Input Method |
|
39 * Status region attached to the given VendorShell. This is needed in order |
|
40 * to calculate geometry for Frames and Dialogs that contain TextField or |
|
41 * TextArea widgets. |
|
42 * |
|
43 * BCB: Copying this function out of the Motif source is a horrible |
|
44 * hack. Unfortunately, Motif tries to hide the existence of the IM Status |
|
45 * region from us so it does not provide any public way to get this info. |
|
46 * Clearly a better long term solution needs to be found. |
|
47 */ |
|
48 |
|
49 typedef struct _XmICStruct { |
|
50 struct _XmICStruct *next; |
|
51 Widget icw; |
|
52 Window focus_window; |
|
53 XtArgVal foreground; |
|
54 XtArgVal background; |
|
55 XtArgVal background_pixmap; |
|
56 XtArgVal font_list; |
|
57 XtArgVal line_space; |
|
58 int32_t status_width; |
|
59 int32_t status_height; |
|
60 int32_t preedit_width; |
|
61 int32_t preedit_height; |
|
62 Boolean has_focus; |
|
63 Boolean need_reset; |
|
64 } XmICStruct; |
|
65 |
|
66 typedef struct { |
|
67 Widget im_widget; |
|
68 XIMStyle input_style; |
|
69 XIC xic; |
|
70 int32_t status_width; |
|
71 int32_t status_height; |
|
72 int32_t preedit_width; |
|
73 int32_t preedit_height; |
|
74 XmICStruct *iclist; |
|
75 XmICStruct *current; |
|
76 } XmImInfo; |
|
77 |
|
78 static XFontSet extract_fontset(XmFontList); |
|
79 static XmICStruct *get_iclist(Widget); |
|
80 |
|
81 #define MAXARGS 10 |
|
82 static Arg xic_vlist[MAXARGS]; |
|
83 static Arg status_vlist[MAXARGS]; |
|
84 static Arg preedit_vlist[MAXARGS]; |
|
85 |
|
86 #define NO_ARG_VAL -1 |
|
87 #define SEPARATOR_HEIGHT 2 |
|
88 |
|
89 |
|
90 #ifdef MOTIF_2_1_HACK |
|
91 /* To shut up warning messages from "cc -v" |
|
92 * Copied from Solaris 2.6 /usr/dt/include/Xm/BaseClassP.h and not |
|
93 * there in Solaris 7. |
|
94 */ |
|
95 #if defined(__SunOS_5_7) || defined(__SunOS_5_8) |
|
96 extern XmWidgetExtData _XmGetWidgetExtData(Widget, unsigned char); |
|
97 #endif |
|
98 |
|
99 #else |
|
100 |
|
101 /* |
|
102 The following defines are to make the XmImGetXIC to compile on systems |
|
103 lower than SunOS 5.7, so therefore the following is a copy of the |
|
104 defines on SunOS 5.7/Motif2.1 header files. |
|
105 */ |
|
106 /*#if defined (__SunOS_5_5_1) || defined (__SunOS_5_6)*/ |
|
107 #define XmPER_SHELL 0 |
|
108 |
|
109 extern XIC XmImGetXIC( |
|
110 Widget w, |
|
111 unsigned int input_policy, |
|
112 ArgList args, |
|
113 Cardinal num_args) ; |
|
114 #endif |
|
115 |
|
116 static XmICStruct * |
|
117 get_iclist(Widget w) |
|
118 { |
|
119 Widget p; |
|
120 XmVendorShellExtObject ve; |
|
121 XmWidgetExtData extData; |
|
122 XmImInfo *im_info; |
|
123 |
|
124 p = w; |
|
125 while (!XtIsShell(p)) |
|
126 p = XtParent(p); |
|
127 |
|
128 extData = (XmWidgetExtData)_XmGetWidgetExtData((Widget) p, XmSHELL_EXTENSION); |
|
129 if (extData == NULL) |
|
130 return NULL; |
|
131 |
|
132 ve = (XmVendorShellExtObject) extData->widget; |
|
133 if ((im_info = (XmImInfo *) ve->vendor.im_info) == NULL) |
|
134 return NULL; |
|
135 else |
|
136 return im_info->iclist; |
|
137 } |
|
138 |
|
139 int32_t |
|
140 awt_motif_getIMStatusHeight(Widget vw, jobject tc) |
|
141 { |
|
142 XmICStruct *icp; |
|
143 XmVendorShellExtObject ve; |
|
144 XmWidgetExtData extData; |
|
145 XmImInfo *im_info; |
|
146 int32_t width = 0; |
|
147 int32_t height = 0; |
|
148 XRectangle rect; |
|
149 XRectangle *rp; |
|
150 int32_t old_height; |
|
151 Arg args[1]; |
|
152 int32_t base_height; |
|
153 XFontSet fs; |
|
154 XFontSet fss = NULL; |
|
155 XFontSet fsp = NULL; |
|
156 |
|
157 extData = (XmWidgetExtData)_XmGetWidgetExtData((Widget) vw, XmSHELL_EXTENSION); |
|
158 ve = (XmVendorShellExtObject) extData->widget; |
|
159 |
|
160 if ((icp = get_iclist(vw)) == NULL) { |
|
161 ve->vendor.im_height = 0; |
|
162 return 0; |
|
163 } |
|
164 im_info = (XmImInfo *) ve->vendor.im_info; |
|
165 if (im_info->xic == NULL) { |
|
166 ve->vendor.im_height = 0; |
|
167 return 0; |
|
168 } |
|
169 status_vlist[0].name = XNFontSet; |
|
170 status_vlist[1].name = NULL; |
|
171 preedit_vlist[0].name = XNFontSet; |
|
172 preedit_vlist[1].name = NULL; |
|
173 |
|
174 xic_vlist[0].name = XNAreaNeeded; |
|
175 xic_vlist[1].name = NULL; |
|
176 |
|
177 im_info->status_width = 0; |
|
178 im_info->status_height = 0; |
|
179 im_info->preedit_width = 0; |
|
180 im_info->preedit_height = 0; |
|
181 for (; icp != NULL; icp = icp->next) { |
|
182 if (im_info->input_style & XIMStatusArea) { |
|
183 if (icp->status_height == 0) { |
|
184 char *ret; |
|
185 |
|
186 if (icp->font_list == NO_ARG_VAL || |
|
187 (fss = extract_fontset((XmFontList) icp->font_list)) == NULL) |
|
188 continue; |
|
189 |
|
190 status_vlist[0].value = (XtArgVal) fss; |
|
191 XSetICValues(im_info->xic, |
|
192 XNStatusAttributes, &status_vlist[0], |
|
193 NULL); |
|
194 |
|
195 xic_vlist[0].value = (XtArgVal) & rp; |
|
196 ret = XGetICValues(im_info->xic, |
|
197 XNStatusAttributes, &xic_vlist[0], |
|
198 NULL); |
|
199 |
|
200 if (ret) { |
|
201 /* Cannot obtain XIC value. IM server may be gone. */ |
|
202 ve->vendor.im_height = 0; |
|
203 return 0; |
|
204 } else { |
|
205 icp->status_width = rp->width; |
|
206 icp->status_height = rp->height; |
|
207 XFree(rp); |
|
208 } |
|
209 } |
|
210 if (icp->status_width > im_info->status_width) |
|
211 im_info->status_width = icp->status_width; |
|
212 if (icp->status_height > im_info->status_height) |
|
213 im_info->status_height = icp->status_height; |
|
214 } |
|
215 if (im_info->input_style & XIMPreeditArea) { |
|
216 if (icp->preedit_height == 0) { |
|
217 if (icp->font_list == NO_ARG_VAL || |
|
218 (fsp = extract_fontset((XmFontList) icp->font_list)) == NULL) |
|
219 continue; |
|
220 |
|
221 preedit_vlist[0].value = (XtArgVal) fsp; |
|
222 XSetICValues(im_info->xic, |
|
223 XNPreeditAttributes, &preedit_vlist[0], |
|
224 NULL); |
|
225 |
|
226 xic_vlist[0].value = (XtArgVal) & rp; |
|
227 XGetICValues(im_info->xic, |
|
228 XNPreeditAttributes, &xic_vlist[0], |
|
229 NULL); |
|
230 |
|
231 icp->preedit_width = rp->width; |
|
232 icp->preedit_height = rp->height; |
|
233 XFree(rp); |
|
234 } |
|
235 if (icp->preedit_width > im_info->preedit_width) |
|
236 im_info->preedit_width = icp->preedit_width; |
|
237 if (icp->preedit_height > im_info->preedit_height) |
|
238 im_info->preedit_height = icp->preedit_height; |
|
239 } |
|
240 } |
|
241 |
|
242 if (im_info->current != NULL && (fss != NULL || fsp != NULL)) { |
|
243 if (im_info->current->font_list != NO_ARG_VAL && |
|
244 (fs = extract_fontset((XmFontList) im_info->current->font_list)) |
|
245 != NULL) { |
|
246 if (fss != NULL) |
|
247 status_vlist[0].value = (XtArgVal) fs; |
|
248 else |
|
249 status_vlist[0].name = NULL; |
|
250 if (fsp != NULL) |
|
251 preedit_vlist[0].value = (XtArgVal) fs; |
|
252 else |
|
253 preedit_vlist[0].name = NULL; |
|
254 XSetICValues(im_info->xic, |
|
255 XNStatusAttributes, &status_vlist[0], |
|
256 XNPreeditAttributes, &preedit_vlist[0], |
|
257 NULL); |
|
258 } |
|
259 } |
|
260 if (im_info->status_height > im_info->preedit_height) |
|
261 height = im_info->status_height; |
|
262 else |
|
263 height = im_info->preedit_height; |
|
264 old_height = ve->vendor.im_height; |
|
265 if (height) |
|
266 height += SEPARATOR_HEIGHT; |
|
267 |
|
268 ve->vendor.im_height = height; |
|
269 |
|
270 XtSetArg(args[0], XtNbaseHeight, &base_height); |
|
271 XtGetValues(vw, args, 1); |
|
272 if (base_height < 0) |
|
273 base_height = 0; |
|
274 XtSetArg(args[0], XtNbaseHeight, base_height); |
|
275 XtSetValues(vw, args, 1); |
|
276 return height; |
|
277 } |
|
278 static XRectangle geometryRect; |
|
279 XVaNestedList awt_motif_getXICStatusAreaList(Widget w, jobject tc) |
|
280 { |
|
281 Widget p; |
|
282 XmVendorShellExtObject ve; |
|
283 XmWidgetExtData extData; |
|
284 XmImInfo *im_info; |
|
285 XmICStruct *icp; |
|
286 |
|
287 XVaNestedList list = NULL; |
|
288 XRectangle *ssgeometry = &geometryRect; |
|
289 Pixel bg; |
|
290 Pixel fg; |
|
291 Pixmap bpm; |
|
292 Dimension height,width; |
|
293 Position x,y; |
|
294 |
|
295 p = w; |
|
296 while (!XtIsShell(p)){ |
|
297 p = XtParent(p); |
|
298 } |
|
299 |
|
300 XtVaGetValues(p, |
|
301 XmNx, &x, |
|
302 XmNy, &y, |
|
303 XmNwidth, &width, |
|
304 XmNheight, &height, |
|
305 NULL); |
|
306 |
|
307 extData = (XmWidgetExtData)_XmGetWidgetExtData((Widget) p, XmSHELL_EXTENSION); |
|
308 if (extData == NULL) { |
|
309 return NULL; |
|
310 } |
|
311 |
|
312 ve = (XmVendorShellExtObject) extData->widget; |
|
313 if ((im_info = (XmImInfo *) ve->vendor.im_info) == NULL) { |
|
314 return NULL; |
|
315 } else |
|
316 icp = im_info->iclist; |
|
317 |
|
318 |
|
319 if (icp) { |
|
320 /* |
|
321 * We hava at least a textfield/textarea in the frame, use the |
|
322 * first one. |
|
323 */ |
|
324 ssgeometry->x = 0; |
|
325 ssgeometry->y = height - icp->status_height; |
|
326 ssgeometry->width = icp->status_width; |
|
327 ssgeometry->height = icp->status_height; |
|
328 |
|
329 /* |
|
330 * use motif TextComponent's resource |
|
331 */ |
|
332 fg = icp->foreground; |
|
333 bg = icp->background; |
|
334 bpm = icp->background_pixmap; |
|
335 |
|
336 list = XVaCreateNestedList(0, |
|
337 XNFontSet, extract_fontset((XmFontList)icp->font_list), |
|
338 XNArea, ssgeometry, |
|
339 XNBackground, bg, |
|
340 XNForeground, fg, |
|
341 XNBackgroundPixmap, bpm, |
|
342 NULL); |
|
343 } |
|
344 return list ; |
|
345 } |
|
346 |
|
347 static XFontSet |
|
348 extract_fontset(XmFontList fl) |
|
349 { |
|
350 XmFontContext context; |
|
351 XmFontListEntry next_entry; |
|
352 XmFontType type_return; |
|
353 XtPointer tmp_font; |
|
354 XFontSet first_fs = NULL; |
|
355 char *font_tag; |
|
356 |
|
357 if (!XmFontListInitFontContext(&context, fl)) |
|
358 return NULL; |
|
359 |
|
360 do { |
|
361 next_entry = XmFontListNextEntry(context); |
|
362 if (next_entry) { |
|
363 tmp_font = XmFontListEntryGetFont(next_entry, &type_return); |
|
364 if (type_return == XmFONT_IS_FONTSET) { |
|
365 font_tag = XmFontListEntryGetTag(next_entry); |
|
366 if (!strcmp(font_tag, XmFONTLIST_DEFAULT_TAG)) { |
|
367 XmFontListFreeFontContext(context); |
|
368 XtFree(font_tag); |
|
369 return (XFontSet) tmp_font; |
|
370 } |
|
371 XtFree(font_tag); |
|
372 if (first_fs == NULL) |
|
373 first_fs = (XFontSet) tmp_font; |
|
374 } |
|
375 } |
|
376 } while (next_entry); |
|
377 |
|
378 XmFontListFreeFontContext(context); |
|
379 return first_fs; |
|
380 } |
|
381 |
|
382 /* |
|
383 * Motif 1.2 requires that an X event passed to XmDragStart is of |
|
384 * ButtonPress type. In Motif 2.1 the restriction is relaxed to allow |
|
385 * ButtonPress, ButtonRelease, KeyRelease, KeyPress, MotionNotify events |
|
386 * as drag initiators. Actually the code in Motif 1.2 works okay for these |
|
387 * events as well, since it uses only the fields that have the same values |
|
388 * in all five event types. To bypass the initial sanity check in |
|
389 * XmDragStart we forcibly change event type to ButtonPress. |
|
390 * |
|
391 * This function causes an UnsatisfiedLinkError on Linux. |
|
392 * Since Linux only links against Motif 2.1, we can safely remove |
|
393 * this function altogether from the Linux build. |
|
394 * bchristi 1/22/2001 |
|
395 */ |
|
396 |
|
397 #ifdef __solaris__ |
|
398 void |
|
399 awt_motif_adjustDragTriggerEvent(XEvent* xevent) { |
|
400 xevent->type = ButtonPress; |
|
401 } |
|
402 #endif /* __solaris__ */ |
|
403 |
|
404 static XmDragStartProc do_drag_start = NULL; |
|
405 static Widget drag_initiator = NULL; |
|
406 |
|
407 static void |
|
408 CheckedDragStart(XmDragContext dc, Widget src, XEvent *event) { |
|
409 DASSERT(do_drag_start != NULL); |
|
410 DASSERT(drag_initiator != NULL); |
|
411 /* |
|
412 * Fix for BugTraq ID 4407057. |
|
413 * Enable the drag operation only if it is registered on the specific widget. |
|
414 * We use this check to disable Motif default drag support. |
|
415 */ |
|
416 if (src == drag_initiator) { |
|
417 do_drag_start(dc, src, event); |
|
418 } else { |
|
419 /* |
|
420 * This is the last chance to destroy the XmDragContext widget. |
|
421 * NOTE: We rely on the fact that Motif 1.2 never uses the pointer |
|
422 * to XmDragContext object returned from XmDragStart. |
|
423 */ |
|
424 XtDestroyWidget(dc); |
|
425 } |
|
426 } |
|
427 |
|
428 void |
|
429 awt_motif_enableSingleDragInitiator(Widget w) { |
|
430 DASSERT(drag_initiator == NULL && do_drag_start == NULL && w != NULL); |
|
431 drag_initiator = w; |
|
432 do_drag_start = xmDragContextClassRec.drag_class.start; |
|
433 DASSERT(do_drag_start != NULL); |
|
434 xmDragContextClassRec.drag_class.start = (XmDragStartProc)CheckedDragStart; |
|
435 } |
|