blob: fc3d90ed99537b0dc9f874f0d85545fe65f9aa40 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
49typedef 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
66typedef 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
78static XFontSet extract_fontset(XmFontList);
79static XmICStruct *get_iclist(Widget);
80
81#define MAXARGS 10
82static Arg xic_vlist[MAXARGS];
83static Arg status_vlist[MAXARGS];
84static 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)
96extern 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
109extern XIC XmImGetXIC(
110 Widget w,
111 unsigned int input_policy,
112 ArgList args,
113 Cardinal num_args) ;
114#endif
115
116static XmICStruct *
117get_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
139int32_t
140awt_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}
278static XRectangle geometryRect;
279XVaNestedList 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
347static XFontSet
348extract_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__
398void
399awt_motif_adjustDragTriggerEvent(XEvent* xevent) {
400 xevent->type = ButtonPress;
401}
402#endif /* __solaris__ */
403
404static XmDragStartProc do_drag_start = NULL;
405static Widget drag_initiator = NULL;
406
407static void
408CheckedDragStart(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
428void
429awt_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}