1 /*
2  * Copyright (c) 2003, 2013, 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 sun.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     final static Unsafe unsafe = Unsafe.getUnsafe();
42 
43     final static int XEMBED_VERSION = 0,
44         XEMBED_MAPPED = (1 << 0);
45 /* XEMBED messages */
46     final static int XEMBED_EMBEDDED_NOTIFY     =       0;
47     final static int XEMBED_WINDOW_ACTIVATE  =  1;
48     final static int XEMBED_WINDOW_DEACTIVATE =         2;
49     final static int XEMBED_REQUEST_FOCUS               =3;
50     final static int XEMBED_FOCUS_IN    =       4;
51     final static int XEMBED_FOCUS_OUT   =       5;
52     final static int XEMBED_FOCUS_NEXT  =       6;
53     final static int XEMBED_FOCUS_PREV  =       7;
54 /* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */
55     final static int XEMBED_GRAB_KEY = 8;
56     final static int XEMBED_UNGRAB_KEY = 9;
57     final static int XEMBED_MODALITY_ON         =       10;
58     final static int XEMBED_MODALITY_OFF        =       11;
59     final static int XEMBED_REGISTER_ACCELERATOR =    12;
60     final static int XEMBED_UNREGISTER_ACCELERATOR=   13;
61     final static int XEMBED_ACTIVATE_ACCELERATOR  =   14;
62 
63     final static int NON_STANDARD_XEMBED_GTK_GRAB_KEY = 108;
64     final static 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     final static int XEMBED_FOCUS_CURRENT       =       0;
69     final static int XEMBED_FOCUS_FIRST         =       1;
70     final static int XEMBED_FOCUS_LAST  =       2;
71 
72 // Modifiers bits
73     final static int XEMBED_MODIFIER_SHIFT   = (1 << 0);
74     final static int XEMBED_MODIFIER_CONTROL = (1 << 1);
75     final static int XEMBED_MODIFIER_ALT     = (1 << 2);
76     final static int XEMBED_MODIFIER_SUPER   = (1 << 3);
77     final static int XEMBED_MODIFIER_HYPER   = (1 << 4);
78 
79     static XAtom XEmbedInfo;
80     static XAtom XEmbed;
81 
XEmbedHelper()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 
sendMessage(long window, int message)97     void sendMessage(long window, int message) {
98         sendMessage(window, message, 0, 0, 0);
99     }
sendMessage(long window, int message, long detail, long data1, long data2)100     void sendMessage(long window, int message, long detail, long data1, long data2) {
101         XClientMessageEvent msg = new XClientMessageEvent();
102         msg.set_type((int)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 
msgidToString(int msg_id)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 
focusIdToString(int focus_id)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 
XEmbedMessageToString(XClientMessageEvent msg)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      */
getModifiers(int state)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.
getKeyStrokeForKeySym(long keysym, long state)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 }
239