1 /*
   2  * Copyright (c) 2003, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.awt.X11;
  27 
  28 import jdk.internal.misc.Unsafe;
  29 
  30 import sun.util.logging.PlatformLogger;
  31 
  32 import java.awt.AWTKeyStroke;
  33 import java.awt.event.InputEvent;
  34 
  35 /**
  36  * Common class for all XEmbed protocol participating classes.
  37  * Contains constant definitions and helper routines.
  38  */
  39 public class XEmbedHelper {
  40     private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed");
  41     static final Unsafe unsafe = Unsafe.getUnsafe();
  42 
  43     static final int XEMBED_VERSION = 0,
  44         XEMBED_MAPPED = (1 << 0);
  45 /* XEMBED messages */
  46     static final int XEMBED_EMBEDDED_NOTIFY     =       0;
  47     static final int XEMBED_WINDOW_ACTIVATE  =  1;
  48     static final int XEMBED_WINDOW_DEACTIVATE =         2;
  49     static final int XEMBED_REQUEST_FOCUS               =3;
  50     static final int XEMBED_FOCUS_IN    =       4;
  51     static final int XEMBED_FOCUS_OUT   =       5;
  52     static final int XEMBED_FOCUS_NEXT  =       6;
  53     static final int XEMBED_FOCUS_PREV  =       7;
  54 /* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */
  55     static final int XEMBED_GRAB_KEY = 8;
  56     static final int XEMBED_UNGRAB_KEY = 9;
  57     static final int XEMBED_MODALITY_ON         =       10;
  58     static final int XEMBED_MODALITY_OFF        =       11;
  59     static final int XEMBED_REGISTER_ACCELERATOR =    12;
  60     static final int XEMBED_UNREGISTER_ACCELERATOR=   13;
  61     static final int XEMBED_ACTIVATE_ACCELERATOR  =   14;
  62 
  63     static final int NON_STANDARD_XEMBED_GTK_GRAB_KEY = 108;
  64     static final int NON_STANDARD_XEMBED_GTK_UNGRAB_KEY = 109;
  65 
  66 //     A detail code is required for XEMBED_FOCUS_IN. The following values are valid:
  67 /* Details for  XEMBED_FOCUS_IN: */
  68     static final int XEMBED_FOCUS_CURRENT       =       0;
  69     static final int XEMBED_FOCUS_FIRST         =       1;
  70     static final int XEMBED_FOCUS_LAST  =       2;
  71 
  72 // Modifiers bits
  73     static final int XEMBED_MODIFIER_SHIFT   = (1 << 0);
  74     static final int XEMBED_MODIFIER_CONTROL = (1 << 1);
  75     static final int XEMBED_MODIFIER_ALT     = (1 << 2);
  76     static final int XEMBED_MODIFIER_SUPER   = (1 << 3);
  77     static final int XEMBED_MODIFIER_HYPER   = (1 << 4);
  78 
  79     static XAtom XEmbedInfo;
  80     static XAtom XEmbed;
  81 
  82     XEmbedHelper() {
  83         if (XEmbed == null) {
  84             XEmbed = XAtom.get("_XEMBED");
  85             if (xembedLog.isLoggable(PlatformLogger.Level.FINER)) {
  86                 xembedLog.finer("Created atom " + XEmbed.toString());
  87             }
  88         }
  89         if (XEmbedInfo == null) {
  90             XEmbedInfo = XAtom.get("_XEMBED_INFO");
  91             if (xembedLog.isLoggable(PlatformLogger.Level.FINER)) {
  92                 xembedLog.finer("Created atom " + XEmbedInfo.toString());
  93             }
  94         }
  95     }
  96 
  97     void sendMessage(long window, int message) {
  98         sendMessage(window, message, 0, 0, 0);
  99     }
 100     void sendMessage(long window, int message, long detail, long data1, long data2) {
 101         XClientMessageEvent msg = new XClientMessageEvent();
 102         msg.set_type(XConstants.ClientMessage);
 103         msg.set_window(window);
 104         msg.set_message_type(XEmbed.getAtom());
 105         msg.set_format(32);
 106         msg.set_data(0, XToolkit.getCurrentServerTime());
 107         msg.set_data(1, message);
 108         msg.set_data(2, detail);
 109         msg.set_data(3, data1);
 110         msg.set_data(4, data2);
 111         XToolkit.awtLock();
 112         try {
 113             if (xembedLog.isLoggable(PlatformLogger.Level.FINE)) {
 114                 xembedLog.fine("Sending " + XEmbedMessageToString(msg));
 115             }
 116             XlibWrapper.XSendEvent(XToolkit.getDisplay(), window, false, XConstants.NoEventMask, msg.pData);
 117         }
 118         finally {
 119             XToolkit.awtUnlock();
 120         }
 121         msg.dispose();
 122     }
 123 
 124     static String msgidToString(int msg_id) {
 125         switch (msg_id) {
 126           case XEMBED_EMBEDDED_NOTIFY:
 127               return "XEMBED_EMBEDDED_NOTIFY";
 128           case XEMBED_WINDOW_ACTIVATE:
 129               return "XEMBED_WINDOW_ACTIVATE";
 130           case XEMBED_WINDOW_DEACTIVATE:
 131               return "XEMBED_WINDOW_DEACTIVATE";
 132           case XEMBED_FOCUS_IN:
 133               return "XEMBED_FOCUS_IN";
 134           case XEMBED_FOCUS_OUT:
 135               return "XEMBED_FOCUS_OUT";
 136           case XEMBED_REQUEST_FOCUS:
 137               return "XEMBED_REQUEST_FOCUS";
 138           case XEMBED_FOCUS_NEXT:
 139               return "XEMBED_FOCUS_NEXT";
 140           case XEMBED_FOCUS_PREV:
 141               return "XEMBED_FOCUS_PREV";
 142           case XEMBED_MODALITY_ON:
 143               return "XEMBED_MODALITY_ON";
 144           case XEMBED_MODALITY_OFF:
 145               return "XEMBED_MODALITY_OFF";
 146           case XEMBED_REGISTER_ACCELERATOR:
 147               return "XEMBED_REGISTER_ACCELERATOR";
 148           case XEMBED_UNREGISTER_ACCELERATOR:
 149               return "XEMBED_UNREGISTER_ACCELERATOR";
 150           case XEMBED_ACTIVATE_ACCELERATOR:
 151               return "XEMBED_ACTIVATE_ACCELERATOR";
 152           case XEMBED_GRAB_KEY:
 153               return "XEMBED_GRAB_KEY";
 154           case XEMBED_UNGRAB_KEY:
 155               return "XEMBED_UNGRAB_KEY";
 156           case NON_STANDARD_XEMBED_GTK_UNGRAB_KEY:
 157               return "NON_STANDARD_XEMBED_GTK_UNGRAB_KEY";
 158           case NON_STANDARD_XEMBED_GTK_GRAB_KEY:
 159               return "NON_STANDARD_XEMBED_GTK_GRAB_KEY";
 160           case XConstants.KeyPress | XEmbedServerTester.SYSTEM_EVENT_MASK:
 161               return "KeyPress";
 162           case XConstants.MapNotify | XEmbedServerTester.SYSTEM_EVENT_MASK:
 163               return "MapNotify";
 164           case XConstants.PropertyNotify | XEmbedServerTester.SYSTEM_EVENT_MASK:
 165               return "PropertyNotify";
 166           default:
 167               return "unknown XEMBED id " + msg_id;
 168         }
 169     }
 170 
 171     static String focusIdToString(int focus_id) {
 172         switch(focus_id) {
 173           case XEMBED_FOCUS_CURRENT:
 174               return "XEMBED_FOCUS_CURRENT";
 175           case XEMBED_FOCUS_FIRST:
 176               return "XEMBED_FOCUS_FIRST";
 177           case XEMBED_FOCUS_LAST:
 178               return "XEMBED_FOCUS_LAST";
 179           default:
 180               return "unknown focus id " + focus_id;
 181         }
 182     }
 183 
 184     static String XEmbedMessageToString(XClientMessageEvent msg) {
 185         return ("XEmbed message to " + Long.toHexString(msg.get_window()) + ": " + msgidToString((int)msg.get_data(1)) +
 186                 ", detail: " + msg.get_data(2) +
 187                 ", data:[" + msg.get_data(3) + "," + msg.get_data(4) + "]");
 188 
 189     }
 190 
 191 
 192     /**
 193      * Converts XEMBED modifiers mask into AWT InputEvent mask
 194      */
 195     int getModifiers(int state) {
 196         int mods = 0;
 197         if ((state & XEMBED_MODIFIER_SHIFT) != 0) {
 198             mods |= InputEvent.SHIFT_DOWN_MASK;
 199         }
 200         if ((state & XEMBED_MODIFIER_CONTROL) != 0) {
 201             mods |= InputEvent.CTRL_DOWN_MASK;
 202         }
 203         if ((state & XEMBED_MODIFIER_ALT) != 0) {
 204             mods |= InputEvent.ALT_DOWN_MASK;
 205         }
 206         // FIXME: What is super/hyper?
 207         // FIXME: Experiments show that SUPER is ALT. So what is Alt then?
 208         if ((state & XEMBED_MODIFIER_SUPER) != 0) {
 209             mods |= InputEvent.ALT_DOWN_MASK;
 210         }
 211 //         if ((state & XEMBED_MODIFIER_HYPER) != 0) {
 212 //             mods |= InputEvent.DOWN_MASK;
 213 //         }
 214         return mods;
 215     }
 216 
 217     // Shouldn't be called on Toolkit thread.
 218     AWTKeyStroke getKeyStrokeForKeySym(long keysym, long state) {
 219         XBaseWindow.checkSecurity();
 220 
 221         int keycode;
 222 
 223         XToolkit.awtLock();
 224         try {
 225             XKeysym.Keysym2JavaKeycode kc = XKeysym.getJavaKeycode( keysym );
 226             if(kc == null) {
 227                 keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
 228             }else{
 229                 keycode = kc.getJavaKeycode();
 230             }
 231         } finally {
 232             XToolkit.awtUnlock();
 233         }
 234 
 235         int modifiers = getModifiers((int)state);
 236         return AWTKeyStroke.getAWTKeyStroke(keycode, modifiers);
 237     }
 238 }