jdk/src/solaris/native/sun/awt/awt_xembed.c
changeset 1192 715cf9378c53
parent 1051 90cf935adb35
parent 1191 f142c1da78c2
child 1193 41afb8ee8f45
equal deleted inserted replaced
1051:90cf935adb35 1192:715cf9378c53
     1 /*
       
     2  * Copyright 2003-2005 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 #ifdef HEADLESS
       
    27     #error This file should not be included in headless library
       
    28 #endif
       
    29 
       
    30 #include "awt_p.h"
       
    31 
       
    32 #include <X11/Xproto.h>
       
    33 #include <X11/Xlib.h>
       
    34 #include <X11/Xatom.h>
       
    35 #include <Xm/MwmUtil.h>
       
    36 
       
    37 /* JNI headers */
       
    38 #include "java_awt_Frame.h"     /* for frame state constants */
       
    39 
       
    40 #include "awt_wm.h"
       
    41 #include "awt_util.h"           /* for X11 error handling macros */
       
    42 #include "awt_xembed.h"
       
    43 #include "awt_MToolkit.h"
       
    44 #include "awt_DataTransferer.h"   /* for DECLARE_XXX macros */
       
    45 
       
    46 #ifdef DOTRACE
       
    47 #define MTRACE(param) fprintf(myerr, param)
       
    48 #define MTRACEP1(format, p1) fprintf(myerr, format, p1)
       
    49 #define MTRACEP2(format, p1, p2) fprintf(myerr, format, p1, p2)
       
    50 #define MTRACEP3(format, p1, p2, p3) fprintf(myerr, format, p1, p2, p3)
       
    51 #define MTRACEP4(format, p1, p2, p3, p4) fprintf(myerr, format, p1, p2, p3, p4)
       
    52 #define MTRACEP5(format, p1, p2, p3, p4, p5) fprintf(myerr, format, p1, p2, p3, p4, p5)
       
    53 #define MTRACEP6(format, p1, p2, p3, p4, p5, p6) fprintf(myerr, format, p1, p2, p3, p4, p5, p6)
       
    54 #define MTRACEP7(format, p1, p2, p3, p4, p5, p6, p7) fprintf(myerr, format, p1, p2, p3, p4, p5, p6, p7)
       
    55 #else
       
    56 #define MTRACE(param)
       
    57 #define MTRACEP1(format, p1)
       
    58 #define MTRACEP2(format, p1, p2)
       
    59 #define MTRACEP3(format, p1, p2, p3)
       
    60 #define MTRACEP4(format, p1, p2, p3, p4)
       
    61 #define MTRACEP5(format, p1, p2, p3, p4, p5)
       
    62 #define MTRACEP6(format, p1, p2, p3, p4, p5, p6)
       
    63 #define MTRACEP7(format, p1, p2, p3, p4, p5, p6, p7)
       
    64 #endif
       
    65 
       
    66 #ifdef DOTRACE
       
    67 static FILE* myerr;
       
    68 #endif
       
    69 
       
    70 static Window getParent(Window window);
       
    71 static Window getEmbedder(Window client);
       
    72 static jmethodID handleFocusInMID;
       
    73 
       
    74 const char * error_msg = "UNKNOWN XEMBED MESSAGE";
       
    75 
       
    76 const char * xembed_strs[] = {
       
    77     "EMBEDDED_NOTIFY",
       
    78     "WINDOW_ACTIVATE",
       
    79     "WINDOW_DEACTIVATE",
       
    80     "REQUEST_FOCUS",
       
    81     "FOCUS_IN",
       
    82     "FOCUS_OUT",
       
    83     "FOCUS_NEXT",
       
    84     "FOCUS_PREV" ,
       
    85     "GRAB_KEY",
       
    86     "UNGRAB_KEY",
       
    87     "MODALITY_ON" ,
       
    88     "MODALITY_OFF",
       
    89     "REGISTER_ACCELERATOR",
       
    90     "UNREGISTER_ACCELERATOR",
       
    91     "ACTIVATE_ACCELERATOR"
       
    92 };
       
    93 
       
    94 const char *
       
    95 msg_to_str(int msg) {
       
    96     if (msg >= 0 && msg <= XEMBED_LAST_MSG) {
       
    97         return xembed_strs[msg];
       
    98     } else {
       
    99         return error_msg;
       
   100     }
       
   101 }
       
   102 
       
   103 DECLARE_JAVA_CLASS(MEmbeddedFramePeerClass, "sun/awt/motif/MEmbeddedFramePeer");
       
   104 
       
   105 typedef struct _xembed_info {
       
   106     CARD32 version;
       
   107     CARD32 flags;
       
   108 } xembed_info;
       
   109 
       
   110 typedef struct _xembed_data {
       
   111     struct FrameData * wdata; // pointer to EmbeddedFrame wdata
       
   112     Window client; // pointer to plugin intermediate widget, XEmbed client
       
   113     Boolean active; // whether xembed is active for this client
       
   114     Boolean applicationActive; // whether the embedding application is active
       
   115     Window embedder; // Window ID of the embedder
       
   116     struct _xembed_data * next;
       
   117 } xembed_data, * pxembed_data;
       
   118 
       
   119 static pxembed_data xembed_list = NULL;
       
   120 
       
   121 static pxembed_data
       
   122 getData(Window client) {
       
   123     pxembed_data temp = xembed_list;
       
   124     while (temp != NULL) {
       
   125         if (temp->client == client) {
       
   126             return temp;
       
   127         }
       
   128         temp = temp->next;
       
   129     }
       
   130     return NULL;
       
   131 }
       
   132 
       
   133 static pxembed_data
       
   134 getDataByFrame(struct FrameData* wdata) {
       
   135     pxembed_data temp = xembed_list;
       
   136     while (temp != NULL) {
       
   137         if (temp->wdata == wdata) {
       
   138             return temp;
       
   139         }
       
   140         temp = temp->next;
       
   141     }
       
   142     return NULL;
       
   143 }
       
   144 
       
   145 static pxembed_data
       
   146 addData(Window client) {
       
   147     xembed_data * data = malloc(sizeof(xembed_data));
       
   148     memset(data, 0, sizeof(xembed_data));
       
   149     data->client = client;
       
   150     data->next = xembed_list;
       
   151     xembed_list = data;
       
   152     return data;
       
   153 }
       
   154 
       
   155 static void
       
   156 removeData(Window client) {
       
   157     pxembed_data * temp = &xembed_list;
       
   158     while (*temp != NULL) {
       
   159         if ((*temp)->client == client) {
       
   160             xembed_data * data = *temp;
       
   161             *temp = (*temp)->next;
       
   162             free(data);
       
   163             return;
       
   164         }
       
   165         temp = &(*temp)->next;
       
   166     }
       
   167 }
       
   168 
       
   169 static Atom XA_XEmbedInfo;
       
   170 static Atom XA_XEmbed;
       
   171 
       
   172 void
       
   173 init_xembed() {
       
   174     XA_XEmbedInfo = XInternAtom(awt_display, "_XEMBED_INFO", False);
       
   175     XA_XEmbed = XInternAtom(awt_display, "_XEMBED", False);
       
   176 #ifdef DOTRACE
       
   177     myerr = fopen("xembedclient.log","w");
       
   178 #endif
       
   179 }
       
   180 
       
   181 static Time
       
   182 getCurrentServerTime() {
       
   183     return awt_util_getCurrentServerTime();
       
   184 }
       
   185 
       
   186 
       
   187 void
       
   188 sendMessageHelper(Window window, int message, long detail,
       
   189                               long data1, long data2)
       
   190 {
       
   191     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   192     XEvent ev;
       
   193     XClientMessageEvent * req = (XClientMessageEvent*)&ev;
       
   194     memset(&ev, 0, sizeof(ev));
       
   195 
       
   196     req->type = ClientMessage;
       
   197     req->window = window;
       
   198     req->message_type = XA_XEmbed;
       
   199     req->format = 32;
       
   200     req->data.l[0] = getCurrentServerTime();
       
   201     req->data.l[1] = message;
       
   202     req->data.l[2] = detail;
       
   203     req->data.l[3] = data1;
       
   204     req->data.l[4] = data2;
       
   205     AWT_LOCK();
       
   206     XSendEvent(awt_display, window, False, NoEventMask, &ev);
       
   207     AWT_UNLOCK();
       
   208 }
       
   209 
       
   210 void
       
   211 sendMessage(Window window, int message) {
       
   212     sendMessageHelper(window, message, 0, 0, 0);
       
   213 }
       
   214 
       
   215 
       
   216 static Window
       
   217 getParent(Window window) {
       
   218     Window root, parent = None, *children = NULL;
       
   219     unsigned int count;
       
   220     XQueryTree(awt_display, window, &root, &parent, &children, &count);
       
   221     if (children != NULL) {
       
   222         XFree(children);
       
   223     }
       
   224     return parent;
       
   225 }
       
   226 
       
   227 static Window
       
   228 getEmbedder(Window client) {
       
   229     return getParent(client);
       
   230 }
       
   231 
       
   232 
       
   233 static void
       
   234 handleFocusIn(struct FrameData* wdata, int detail) {
       
   235     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   236     struct WidgetInfo* winfo;
       
   237     MTRACE("HandleFocusIn\n");
       
   238     winfo = findWidgetInfo(wdata->winData.comp.widget);
       
   239     if (winfo != NULL) {
       
   240         jobject peer = winfo->peer;
       
   241         if (handleFocusInMID == NULL) {
       
   242             jclass clazz = (*env)->FindClass(env, "sun/awt/motif/MEmbeddedFramePeer");
       
   243             DASSERT(clazz != NULL);
       
   244             handleFocusInMID = (*env)->GetMethodID(env, clazz, "handleFocusIn", "(I)V");
       
   245             DASSERT(handleFocusInMID != NULL);
       
   246             if (clazz != NULL) {
       
   247                 (*env)->DeleteLocalRef(env, clazz);
       
   248             }
       
   249         }
       
   250         if (handleFocusInMID != NULL) {
       
   251             (*env)->CallVoidMethod(env, peer, handleFocusInMID, (jint)detail);
       
   252         }
       
   253     }
       
   254 }
       
   255 
       
   256 static void
       
   257 genWindowFocus(struct FrameData *wdata, Boolean gain) {
       
   258     XEvent ev;
       
   259     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   260     memset(&ev, 0, sizeof(ev));
       
   261 
       
   262     ev.type = (gain?FocusIn:FocusOut);
       
   263     ev.xany.send_event = True;
       
   264     ev.xany.display = awt_display;
       
   265     ev.xfocus.mode = NotifyNormal;
       
   266     ev.xfocus.detail = NotifyNonlinear;
       
   267     ev.xfocus.window = XtWindow(wdata->winData.shell);
       
   268     awt_put_back_event(env, &ev);
       
   269 }
       
   270 
       
   271 extern Boolean skipNextFocusIn;
       
   272 
       
   273 static void
       
   274 callNotifyStarted(JNIEnv* env, jobject peer) {
       
   275     DECLARE_VOID_JAVA_METHOD(notifyStartedMID, MEmbeddedFramePeerClass,
       
   276                              "notifyStarted", "()V");
       
   277 
       
   278     (*env)->CallVoidMethod(env, peer, notifyStartedMID);
       
   279 }
       
   280 
       
   281 void
       
   282 xembed_eventHandler(XEvent *event)
       
   283 {
       
   284     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   285     struct FrameData *wdata;
       
   286     xembed_data * data;
       
   287 
       
   288     data = getData(event->xany.window);
       
   289     if (data == NULL) {
       
   290         MTRACEP1("No XEMBED client registered for this window %x\n", event->xany.window);
       
   291         if (event->xany.type == ClientMessage) {
       
   292             MTRACEP7("Unprocessed handleClientMessage: type=%d 0=%ld 1=%ld(%s) 2=%ld 3=%ld 4=%ld\n",
       
   293                      event->xclient.message_type, event->xclient.data.l[0],
       
   294                      event->xclient.data.l[1], msg_to_str(event->xclient.data.l[1]),
       
   295                      event->xclient.data.l[2],
       
   296                      event->xclient.data.l[3], event->xclient.data.l[4]);
       
   297         }
       
   298         return;
       
   299     }
       
   300 
       
   301     wdata = data->wdata;
       
   302 
       
   303     if (event->xany.type == ClientMessage) {
       
   304         MTRACEP6("handleClientMessage: type=%d 0=%ld 1=%ld 2=%ld 3=%ld 4=%ld\n",
       
   305                  event->xclient.message_type, event->xclient.data.l[0],
       
   306                  event->xclient.data.l[1], event->xclient.data.l[2],
       
   307                  event->xclient.data.l[3], event->xclient.data.l[4]);
       
   308         // Probably a message from embedder
       
   309         if (event->xclient.message_type == XA_XEmbed) {
       
   310             // XEmbed message, data[1] contains message
       
   311             switch ((int)event->xclient.data.l[1]) {
       
   312               case XEMBED_EMBEDDED_NOTIFY:
       
   313                   MTRACE("EMBEDDED_NOTIFY\n");
       
   314                   data->active = True;
       
   315                   data->embedder = getEmbedder(data->client);
       
   316                   // If Frame has not been reparented already we should "reparent"
       
   317                   // it manually
       
   318                   if (!(wdata->reparented)) {
       
   319                       wdata->reparented = True;
       
   320                       // in XAWT we also update WM_NORMAL_HINTS here.
       
   321                   }
       
   322                   {
       
   323                       struct WidgetInfo* winfo =
       
   324                           findWidgetInfo(wdata->winData.comp.widget);
       
   325                       JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_4);
       
   326                       if (winfo != NULL) {
       
   327                           callNotifyStarted(env, winfo->peer);
       
   328                       }
       
   329                   }
       
   330                   MTRACE("Embedded notify in client\n");
       
   331                   break;
       
   332               case XEMBED_WINDOW_DEACTIVATE:
       
   333                   MTRACE("DEACTIVATE\n");
       
   334                   data->applicationActive = False;
       
   335                   break;
       
   336               case XEMBED_WINDOW_ACTIVATE:
       
   337                   MTRACE("ACTIVATE\n");
       
   338                   data->applicationActive = True;
       
   339                   break;
       
   340               case XEMBED_FOCUS_IN:
       
   341                   MTRACE("FOCUS IN\n");
       
   342                   skipNextFocusIn = False;
       
   343                   handleFocusIn(wdata, (int)(event->xclient.data.l[2]));
       
   344                   genWindowFocus(wdata, True);
       
   345                   break;
       
   346               case XEMBED_FOCUS_OUT:
       
   347                   MTRACE("FOCUS OUT\n");
       
   348                   genWindowFocus(wdata, False);
       
   349                   break;
       
   350             }
       
   351         }
       
   352     } else if (event->xany.type == ReparentNotify) {
       
   353         data->embedder = event->xreparent.parent;
       
   354     }
       
   355 }
       
   356 
       
   357 void
       
   358 notify_ready(Window client) {
       
   359     sendMessage(getEmbedder(client), _SUN_XEMBED_START);
       
   360 }
       
   361 
       
   362 void
       
   363 install_xembed(Widget client_widget, struct FrameData* wdata) {
       
   364     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   365     xembed_info info = {XEMBED_VERSION, XEMBED_MAPPED};
       
   366     Window client = XtWindow(client_widget);
       
   367     xembed_data * data;
       
   368 
       
   369     AWT_LOCK();
       
   370     data = addData(client);
       
   371     data->wdata = wdata;
       
   372 
       
   373     // Install event handler for messages from embedder
       
   374     XSelectInput(awt_display, client, StructureNotifyMask);
       
   375 
       
   376     // Install XEMBED_INFO information
       
   377     XChangeProperty(awt_display, client, XA_XEmbedInfo,
       
   378                     XA_XEmbedInfo, 32, PropModeReplace,
       
   379                     (unsigned char*)&info, 2);
       
   380     MTRACE("Installing xembed\n");
       
   381 
       
   382     notify_ready(client);
       
   383 
       
   384     AWT_UNLOCK();
       
   385 }
       
   386 
       
   387 void
       
   388 deinstall_xembed(struct FrameData* wdata) {
       
   389     xembed_data * data = getDataByFrame(wdata);
       
   390 
       
   391     if (data != NULL) {
       
   392         removeData(data->client);
       
   393     }
       
   394 }
       
   395 
       
   396 void
       
   397 requestXEmbedFocus(struct FrameData * wdata) {
       
   398     xembed_data * data = getDataByFrame(wdata);
       
   399 
       
   400     if (data != NULL) {
       
   401         if (data->active && data->applicationActive) {
       
   402             sendMessage(data->embedder, XEMBED_REQUEST_FOCUS);
       
   403         }
       
   404     }
       
   405 }
       
   406 
       
   407 Boolean
       
   408 isXEmbedActive(struct FrameData * wdata) {
       
   409     xembed_data * data = getDataByFrame(wdata);
       
   410     return (data != NULL && data->active);
       
   411 }
       
   412 
       
   413 Boolean
       
   414 isXEmbedActiveByWindow(Window client) {
       
   415     xembed_data * data = getData(client);
       
   416     return (data != NULL && data->active);
       
   417 }
       
   418 
       
   419 
       
   420 Boolean
       
   421 isXEmbedApplicationActive(struct FrameData * wdata) {
       
   422     xembed_data * data = getDataByFrame(wdata);
       
   423     return (data != NULL && data->applicationActive);
       
   424 }
       
   425 
       
   426 void
       
   427 xembed_traverse_out(struct FrameData * wdata, jboolean direction) {
       
   428     xembed_data * data = getDataByFrame(wdata);
       
   429     sendMessage(data->embedder, (direction == JNI_TRUE)?XEMBED_FOCUS_NEXT:XEMBED_FOCUS_PREV);
       
   430 }