jdk/src/solaris/native/sun/awt/awt_motif12.c
changeset 1211 b659a7cee935
parent 1210 7798f9e88bf9
parent 1203 3e5496df0d2b
child 1212 d718a4419361
equal deleted inserted replaced
1210:7798f9e88bf9 1211:b659a7cee935
     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 }