jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java
changeset 2 90ce3da70b43
child 120 98296a9fc072
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2003-2007 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 package sun.awt.X11;
       
    27 
       
    28 import java.awt.AWTKeyStroke;
       
    29 import java.util.logging.*;
       
    30 import sun.awt.SunToolkit;
       
    31 import java.awt.Component;
       
    32 import java.awt.Container;
       
    33 
       
    34 /**
       
    35  * Helper class implementing XEmbed protocol handling routines(client side)
       
    36  * Window which wants to participate in a protocol should create an instance,
       
    37  * call install and forward all XClientMessageEvents to it.
       
    38  */
       
    39 public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher {
       
    40     private static final Logger xembedLog = Logger.getLogger("sun.awt.X11.xembed.XEmbedClientHelper");
       
    41 
       
    42     private XEmbeddedFramePeer embedded;
       
    43     private boolean active;
       
    44     private long server;
       
    45     private boolean applicationActive;
       
    46 
       
    47     XEmbedClientHelper() {
       
    48         super();
       
    49     }
       
    50 
       
    51     void install(XEmbeddedFramePeer embedded) {
       
    52         this.embedded = embedded;
       
    53 
       
    54         if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Installing xembedder on " + embedded);
       
    55         XToolkit.addEventDispatcher(embedded.getWindow(), this);
       
    56         long[] info = new long[] { XEMBED_VERSION, XEMBED_MAPPED };
       
    57         long data = Native.card32ToData(info);
       
    58         try {
       
    59             XEmbedInfo.setAtomData(embedded.getWindow(), data, 2);
       
    60         } finally {
       
    61             unsafe.freeMemory(data);
       
    62         }
       
    63         // XEmbeddedFrame is initially created with a null parent..
       
    64         // Here it is reparented to the proper parent window.
       
    65         long parentWindow = embedded.getParentWindowHandle();
       
    66         if (parentWindow != 0) {
       
    67             XToolkit.awtLock();
       
    68             try {
       
    69                 XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
       
    70                                             embedded.getWindow(),
       
    71                                             parentWindow,
       
    72                                             0, 0);
       
    73             } finally {
       
    74                 XToolkit.awtUnlock();
       
    75             }
       
    76         }
       
    77         notifyReady();
       
    78     }
       
    79 
       
    80     void handleClientMessage(XEvent xev) {
       
    81         XClientMessageEvent msg = xev.get_xclient();
       
    82         if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine(msg.toString());
       
    83         if (msg.get_message_type() == XEmbed.getAtom()) {
       
    84             if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Embedded message: " + msgidToString((int)msg.get_data(1)));
       
    85             switch ((int)msg.get_data(1)) {
       
    86               case XEMBED_EMBEDDED_NOTIFY: // Notification about embedding protocol start
       
    87                   // NOTE: May be called two times because we send _SUN_XEMBED_START
       
    88                   active = true;
       
    89                   server = getEmbedder(embedded, msg);
       
    90                   // Check if window is reparented. If not - it was created with
       
    91                   // parent and so we should update it here.
       
    92                   if (!embedded.isReparented()) {
       
    93                       embedded.setReparented(true);
       
    94                       embedded.updateSizeHints();
       
    95                   }
       
    96                   embedded.notifyStarted();
       
    97                   break;
       
    98               case XEMBED_WINDOW_ACTIVATE:
       
    99                   applicationActive = true;
       
   100                   break;
       
   101               case XEMBED_WINDOW_DEACTIVATE:
       
   102                   if (applicationActive) {
       
   103                       applicationActive = false;
       
   104                       handleWindowFocusOut();
       
   105                   }
       
   106                   break;
       
   107               case XEMBED_FOCUS_IN: // We got focus!
       
   108                   // Check for direction
       
   109                   handleFocusIn((int)msg.get_data(2));
       
   110                   break;
       
   111               case XEMBED_FOCUS_OUT:
       
   112                   if (applicationActive) {
       
   113                       handleWindowFocusOut();
       
   114                   }
       
   115                   break;
       
   116             }
       
   117         }
       
   118     }
       
   119     void handleFocusIn(int detail) {
       
   120         if (embedded.focusAllowedFor()) {
       
   121             embedded.handleWindowFocusInSync(0);
       
   122         }
       
   123         switch(detail) {
       
   124           case XEMBED_FOCUS_CURRENT:
       
   125               // Do nothing - just restore to the current value
       
   126               break;
       
   127           case XEMBED_FOCUS_FIRST:
       
   128               SunToolkit.executeOnEventHandlerThread(embedded.target, new Runnable() {
       
   129                       public void run() {
       
   130                           Component comp = ((Container)embedded.target).getFocusTraversalPolicy().getFirstComponent((Container)embedded.target);
       
   131                           if (comp != null) {
       
   132                               comp.requestFocusInWindow();
       
   133                           }
       
   134                       }});
       
   135               break;
       
   136           case XEMBED_FOCUS_LAST:
       
   137               SunToolkit.executeOnEventHandlerThread(embedded.target, new Runnable() {
       
   138                       public void run() {
       
   139                           Component comp = ((Container)embedded.target).getFocusTraversalPolicy().getLastComponent((Container)embedded.target);
       
   140                           if (comp != null) {
       
   141                               comp.requestFocusInWindow();
       
   142                           }
       
   143                       }});
       
   144               break;
       
   145         }
       
   146     }
       
   147 
       
   148     public void dispatchEvent(XEvent xev) {
       
   149         switch(xev.get_type()) {
       
   150           case XlibWrapper.ClientMessage:
       
   151               handleClientMessage(xev);
       
   152               break;
       
   153           case XlibWrapper.ReparentNotify:
       
   154               handleReparentNotify(xev);
       
   155               break;
       
   156         }
       
   157     }
       
   158     public void handleReparentNotify(XEvent xev) {
       
   159         XReparentEvent re = xev.get_xreparent();
       
   160         server = re.get_parent();
       
   161     }
       
   162     boolean requestFocus() {
       
   163         if (active && embedded.focusAllowedFor()) {
       
   164             sendMessage(server, XEMBED_REQUEST_FOCUS);
       
   165             return true;
       
   166         }
       
   167         return false;
       
   168     }
       
   169     void handleWindowFocusOut() {
       
   170         // fix for 6269309: it is possible that we call this method twice
       
   171         // (for example, when receiving XEMBED_WINDOW_DEACTIVATE and then
       
   172         // XEMBED_FOCUS_OUT client messages), so we first need to check if
       
   173         // embedded is an active window before sending WINDOW_LOST_FOCUS
       
   174         // to shared code
       
   175         if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == embedded.target) {
       
   176             embedded.handleWindowFocusOutSync(null, 0);
       
   177         }
       
   178     }
       
   179 
       
   180     long getEmbedder(XWindowPeer embedded, XClientMessageEvent info) {
       
   181         // Embedder is the parent of embedded.
       
   182         return XlibUtil.getParentWindow(embedded.getWindow());
       
   183     }
       
   184 
       
   185     boolean isApplicationActive() {
       
   186         return applicationActive;
       
   187     }
       
   188 
       
   189     boolean isActive() {
       
   190         return active;
       
   191     }
       
   192 
       
   193     void traverseOutForward() {
       
   194         if (active) {
       
   195             sendMessage(server, XEMBED_FOCUS_NEXT);
       
   196         }
       
   197     }
       
   198 
       
   199     void traverseOutBackward() {
       
   200         if (active) {
       
   201             sendMessage(server, XEMBED_FOCUS_PREV);
       
   202         }
       
   203     }
       
   204 
       
   205     void registerAccelerator(AWTKeyStroke stroke, int id) {
       
   206         long sym = getX11KeySym(stroke);
       
   207         long mods = getX11Mods(stroke);
       
   208         sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods);
       
   209     }
       
   210     void unregisterAccelerator(int id) {
       
   211         sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0);
       
   212     }
       
   213 
       
   214     long getX11KeySym(AWTKeyStroke stroke) {
       
   215         XToolkit.awtLock();
       
   216         try {
       
   217             return XWindow.getKeySymForAWTKeyCode(stroke.getKeyCode());
       
   218         } finally {
       
   219             XToolkit.awtUnlock();
       
   220         }
       
   221     }
       
   222 
       
   223     long getX11Mods(AWTKeyStroke stroke) {
       
   224         return XWindow.getXModifiers(stroke);
       
   225     }
       
   226 
       
   227     void notifyReady() {
       
   228         long wnd = server;
       
   229         if (wnd == 0) {
       
   230             // Server is still 0, get the parent
       
   231             wnd = embedded.getParentWindowHandle();
       
   232         }
       
   233         sendMessage(wnd, _SUN_XEMBED_START);
       
   234     }
       
   235 }