Source Code Cross Referenced for XEmbedCanvasPeer.java in  » 6.0-JDK-Platform » solaris » sun » awt » X11 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Platform » solaris » sun.awt.X11 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package sun.awt.X11;
027:
028:        import java.awt.*;
029:        import java.awt.dnd.DropTarget;
030:        import java.awt.dnd.DropTargetListener;
031:        import java.awt.event.*;
032:        import java.awt.image.ColorModel;
033:        import java.awt.image.ImageObserver;
034:        import java.awt.image.ImageProducer;
035:        import java.awt.image.VolatileImage;
036:        import java.awt.peer.*;
037:        import sun.awt.*;
038:        import sun.awt.motif.X11FontMetrics;
039:        import java.lang.reflect.*;
040:        import java.util.logging.*;
041:        import java.util.*;
042:        import static sun.awt.X11.XEmbedHelper.*;
043:
044:        import java.security.AccessController;
045:        import sun.security.action.GetBooleanAction;
046:
047:        public class XEmbedCanvasPeer extends XCanvasPeer implements 
048:                WindowFocusListener, KeyEventPostProcessor, ModalityListener,
049:                WindowIDProvider {
050:            private static final Logger xembedLog = Logger
051:                    .getLogger("sun.awt.X11.xembed.XEmbedCanvasPeer");
052:
053:            boolean applicationActive; // Whether the application is active(has focus)
054:            XEmbedServer xembed = new XEmbedServer(); // Helper object, contains XEmbed intrinsics
055:            Map<Long, AWTKeyStroke> accelerators = new HashMap<Long, AWTKeyStroke>(); // Maps accelerator ID into AWTKeyStroke
056:            Map<AWTKeyStroke, Long> accel_lookup = new HashMap<AWTKeyStroke, Long>(); // Maps AWTKeyStroke into accelerator ID
057:            Set<GrabbedKey> grabbed_keys = new HashSet<GrabbedKey>(); // A set of keys grabbed by client
058:            Object ACCEL_LOCK = accelerators; // Lock object for working with accelerators;
059:            Object GRAB_LOCK = grabbed_keys; // Lock object for working with keys grabbed by client
060:
061:            XEmbedCanvasPeer() {
062:            }
063:
064:            XEmbedCanvasPeer(XCreateWindowParams params) {
065:                super (params);
066:            }
067:
068:            XEmbedCanvasPeer(Component target) {
069:                super (target);
070:            }
071:
072:            protected void postInit(XCreateWindowParams params) {
073:                super .postInit(params);
074:
075:                installActivateListener();
076:                installAcceleratorListener();
077:                installModalityListener();
078:
079:                // XEmbed canvas should be non-traversable.
080:                // FIXME: Probably should be removed and enforced setting of it by the users
081:                target.setFocusTraversalKeysEnabled(false);
082:            }
083:
084:            protected void preInit(XCreateWindowParams params) {
085:                super .preInit(params);
086:
087:                params.put(EVENT_MASK, KeyPressMask | KeyReleaseMask
088:                        | FocusChangeMask | ButtonPressMask | ButtonReleaseMask
089:                        | EnterWindowMask | LeaveWindowMask | PointerMotionMask
090:                        | ButtonMotionMask | ExposureMask | StructureNotifyMask
091:                        | SubstructureNotifyMask);
092:
093:            }
094:
095:            void installModalityListener() {
096:                ((SunToolkit) Toolkit.getDefaultToolkit())
097:                        .addModalityListener(this );
098:            }
099:
100:            void deinstallModalityListener() {
101:                ((SunToolkit) Toolkit.getDefaultToolkit())
102:                        .removeModalityListener(this );
103:            }
104:
105:            void installAcceleratorListener() {
106:                KeyboardFocusManager.getCurrentKeyboardFocusManager()
107:                        .addKeyEventPostProcessor(this );
108:            }
109:
110:            void deinstallAcceleratorListener() {
111:                KeyboardFocusManager.getCurrentKeyboardFocusManager()
112:                        .removeKeyEventPostProcessor(this );
113:            }
114:
115:            void installActivateListener() {
116:                // FIXME: should watch for hierarchy changes
117:                Window toplevel = getTopLevel(target);
118:                if (toplevel != null) {
119:                    toplevel.addWindowFocusListener(this );
120:                    applicationActive = toplevel.isFocused();
121:                }
122:            }
123:
124:            void deinstallActivateListener() {
125:                Window toplevel = getTopLevel(target);
126:                if (toplevel != null) {
127:                    toplevel.removeWindowFocusListener(this );
128:                }
129:            }
130:
131:            boolean isXEmbedActive() {
132:                return xembed.handle != 0;
133:            }
134:
135:            boolean isApplicationActive() {
136:                return applicationActive;
137:            }
138:
139:            void initDispatching() {
140:                if (xembedLog.isLoggable(Level.FINE))
141:                    xembedLog.fine("Init embedding for "
142:                            + Long.toHexString(xembed.handle));
143:                XToolkit.awtLock();
144:                try {
145:                    XToolkit.addEventDispatcher(xembed.handle, xembed);
146:                    XlibWrapper.XSelectInput(XToolkit.getDisplay(),
147:                            xembed.handle, XlibWrapper.StructureNotifyMask
148:                                    | XlibWrapper.PropertyChangeMask);
149:
150:                    XDropTargetRegistry.getRegistry().registerXEmbedClient(
151:                            getWindow(), xembed.handle);
152:                } finally {
153:                    XToolkit.awtUnlock();
154:                }
155:                xembed.processXEmbedInfo();
156:
157:                notifyChildEmbedded();
158:            }
159:
160:            void endDispatching() {
161:                xembedLog.fine("End dispatching for "
162:                        + Long.toHexString(xembed.handle));
163:                XToolkit.awtLock();
164:                try {
165:                    XDropTargetRegistry.getRegistry().unregisterXEmbedClient(
166:                            getWindow(), xembed.handle);
167:                    // We can't deselect input since someone else might be interested in it
168:                    XToolkit.removeEventDispatcher(xembed.handle, xembed);
169:                } finally {
170:                    XToolkit.awtUnlock();
171:                }
172:            }
173:
174:            void embedChild(long child) {
175:                if (xembed.handle != 0) {
176:                    detachChild();
177:                }
178:                xembed.handle = child;
179:                initDispatching();
180:            }
181:
182:            void childDestroyed() {
183:                xembedLog.fine("Child " + Long.toHexString(xembed.handle)
184:                        + " has self-destroyed.");
185:                endDispatching();
186:                xembed.handle = 0;
187:            }
188:
189:            public void handleEvent(AWTEvent e) {
190:                super .handleEvent(e);
191:                if (isXEmbedActive()) {
192:                    switch (e.getID()) {
193:                    case FocusEvent.FOCUS_GAINED:
194:                        canvasFocusGained((FocusEvent) e);
195:                        break;
196:                    case FocusEvent.FOCUS_LOST:
197:                        canvasFocusLost((FocusEvent) e);
198:                        break;
199:                    case KeyEvent.KEY_PRESSED:
200:                    case KeyEvent.KEY_RELEASED:
201:                        if (!((InputEvent) e).isConsumed()) {
202:                            forwardKeyEvent((KeyEvent) e);
203:                        }
204:                        break;
205:                    }
206:                }
207:            }
208:
209:            public void dispatchEvent(XEvent ev) {
210:                super .dispatchEvent(ev);
211:                switch (ev.get_type()) {
212:                case CreateNotify:
213:                    XCreateWindowEvent cr = ev.get_xcreatewindow();
214:                    if (xembedLog.isLoggable(Level.FINEST)) {
215:                        xembedLog.finest("Message on embedder: " + cr);
216:                    }
217:                    if (xembedLog.isLoggable(Level.FINER)) {
218:                        xembedLog.finer("Create notify for parent "
219:                                + Long.toHexString(cr.get_parent())
220:                                + ", window "
221:                                + Long.toHexString(cr.get_window()));
222:                    }
223:                    embedChild(cr.get_window());
224:                    break;
225:                case DestroyNotify:
226:                    XDestroyWindowEvent dn = ev.get_xdestroywindow();
227:                    if (xembedLog.isLoggable(Level.FINEST)) {
228:                        xembedLog.finest("Message on embedder: " + dn);
229:                    }
230:                    if (xembedLog.isLoggable(Level.FINER)) {
231:                        xembedLog.finer("Destroy notify for parent: " + dn);
232:                    }
233:                    childDestroyed();
234:                    break;
235:                case ReparentNotify:
236:                    XReparentEvent rep = ev.get_xreparent();
237:                    if (xembedLog.isLoggable(Level.FINEST)) {
238:                        xembedLog.finest("Message on embedder: " + rep);
239:                    }
240:                    if (xembedLog.isLoggable(Level.FINER)) {
241:                        xembedLog.finer("Reparent notify for parent "
242:                                + Long.toHexString(rep.get_parent())
243:                                + ", window "
244:                                + Long.toHexString(rep.get_window())
245:                                + ", event "
246:                                + Long.toHexString(rep.get_event()));
247:                    }
248:                    if (rep.get_parent() == getWindow()) {
249:                        // Reparented into us - embed it
250:                        embedChild(rep.get_window());
251:                    } else {
252:                        // Reparented out of us - detach it
253:                        childDestroyed();
254:                    }
255:                    break;
256:                }
257:            }
258:
259:            public Dimension getPreferredSize() {
260:                if (isXEmbedActive()) {
261:                    XToolkit.awtLock();
262:                    try {
263:                        long p_hints = XlibWrapper.XAllocSizeHints();
264:                        XSizeHints hints = new XSizeHints(p_hints);
265:                        XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(),
266:                                xembed.handle, p_hints, XlibWrapper.larg1);
267:                        Dimension res = new Dimension(hints.get_width(), hints
268:                                .get_height());
269:                        XlibWrapper.XFree(p_hints);
270:                        return res;
271:                    } finally {
272:                        XToolkit.awtUnlock();
273:                    }
274:                } else {
275:                    return super .getPreferredSize();
276:                }
277:            }
278:
279:            public Dimension getMinimumSize() {
280:                if (isXEmbedActive()) {
281:                    XToolkit.awtLock();
282:                    try {
283:                        long p_hints = XlibWrapper.XAllocSizeHints();
284:                        XSizeHints hints = new XSizeHints(p_hints);
285:                        XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(),
286:                                xembed.handle, p_hints, XlibWrapper.larg1);
287:                        Dimension res = new Dimension(hints.get_min_width(),
288:                                hints.get_min_height());
289:                        XlibWrapper.XFree(p_hints);
290:                        return res;
291:                    } finally {
292:                        XToolkit.awtUnlock();
293:                    }
294:                } else {
295:                    return super .getMinimumSize();
296:                }
297:            }
298:
299:            public void dispose() {
300:                if (isXEmbedActive()) {
301:                    detachChild();
302:                }
303:                deinstallActivateListener();
304:                deinstallModalityListener();
305:                deinstallAcceleratorListener();
306:
307:                // BUG: Focus traversal doesn't become enabled after the one round of embedding
308:                //target.setFocusTraversalKeysEnabled(true);
309:
310:                super .dispose();
311:            }
312:
313:            // Focusable is true in order to enable focus traversal through this Canvas
314:            public boolean isFocusable() {
315:                return true;
316:            }
317:
318:            Window getTopLevel(Component comp) {
319:                while (comp != null && !(comp instanceof  Window)) {
320:                    comp = comp.getParent();
321:                }
322:                return (Window) comp;
323:            }
324:
325:            Rectangle getClientBounds() {
326:                XToolkit.awtLock();
327:                try {
328:                    XWindowAttributes wattr = new XWindowAttributes();
329:                    try {
330:                        XToolkit
331:                                .WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
332:                        int status = XlibWrapper.XGetWindowAttributes(XToolkit
333:                                .getDisplay(), xembed.handle, wattr.pData);
334:
335:                        XToolkit.RESTORE_XERROR_HANDLER();
336:
337:                        if (status == 0
338:                                || (XToolkit.saved_error != null && XToolkit.saved_error
339:                                        .get_error_code() != XlibWrapper.Success)) {
340:                            return null;
341:                        }
342:
343:                        return new Rectangle(wattr.get_x(), wattr.get_y(),
344:                                wattr.get_width(), wattr.get_height());
345:                    } finally {
346:                        wattr.dispose();
347:                    }
348:                } finally {
349:                    XToolkit.awtUnlock();
350:                }
351:            }
352:
353:            void childResized() {
354:                if (xembedLog.isLoggable(Level.FINER)) {
355:                    Rectangle bounds = getClientBounds();
356:                    xembedLog.finer("Child resized: " + bounds);
357:                    // It is not required to update embedder's size when client size changes
358:                    // However, since there is no any means to get client size it seems to be the
359:                    // only way to provide it. However, it contradicts with Java layout concept - 
360:                    // so it is disabled for now.
361:                    //             Rectangle my_bounds = getBounds();
362:                    //             setBounds(my_bounds.x, my_bounds.y, bounds.width, bounds.height, SET_BOUNDS);
363:                }
364:                XToolkit.postEvent(XToolkit.targetToAppContext(target),
365:                        new ComponentEvent(target,
366:                                ComponentEvent.COMPONENT_RESIZED));
367:            }
368:
369:            void focusNext() {
370:                if (isXEmbedActive()) {
371:                    xembedLog
372:                            .fine("Requesting focus for the next component after embedder");
373:                    postEvent(new InvocationEvent(target, new Runnable() {
374:                        public void run() {
375:                            KeyboardFocusManager
376:                                    .getCurrentKeyboardFocusManager()
377:                                    .focusNextComponent(target);
378:                        }
379:                    }));
380:                } else {
381:                    xembedLog.fine("XEmbed is not active - denying focus next");
382:                }
383:            }
384:
385:            void focusPrev() {
386:                if (isXEmbedActive()) {
387:                    xembedLog
388:                            .fine("Requesting focus for the next component after embedder");
389:                    postEvent(new InvocationEvent(target, new Runnable() {
390:                        public void run() {
391:                            KeyboardFocusManager
392:                                    .getCurrentKeyboardFocusManager()
393:                                    .focusPreviousComponent(target);
394:                        }
395:                    }));
396:                } else {
397:                    xembedLog.fine("XEmbed is not active - denying focus prev");
398:                }
399:            }
400:
401:            void requestXEmbedFocus() {
402:                if (isXEmbedActive()) {
403:                    xembedLog.fine("Requesting focus for client");
404:                    postEvent(new InvocationEvent(target, new Runnable() {
405:                        public void run() {
406:                            target.requestFocus();
407:                        }
408:                    }));
409:                } else {
410:                    xembedLog
411:                            .fine("XEmbed is not active - denying request focus");
412:                }
413:            }
414:
415:            void notifyChildEmbedded() {
416:                xembed.sendMessage(xembed.handle, XEMBED_EMBEDDED_NOTIFY,
417:                        getWindow(), Math.min(xembed.version, XEMBED_VERSION),
418:                        0);
419:                if (isApplicationActive()) {
420:                    xembedLog
421:                            .fine("Sending WINDOW_ACTIVATE during initialization");
422:                    xembed.sendMessage(xembed.handle, XEMBED_WINDOW_ACTIVATE);
423:                    if (hasFocus()) {
424:                        xembedLog
425:                                .fine("Sending FOCUS_GAINED during initialization");
426:                        xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN,
427:                                XEMBED_FOCUS_CURRENT, 0, 0);
428:                    }
429:                }
430:            }
431:
432:            void detachChild() {
433:                if (xembedLog.isLoggable(Level.FINE))
434:                    xembedLog.fine("Detaching child "
435:                            + Long.toHexString(xembed.handle));
436:                /**
437:                 *  XEmbed specification:
438:                 *  "The embedder can unmap the client and reparent the client window to the root window. If the
439:                 *  client receives an ReparentNotify event, it should check the parent field of the XReparentEvent
440:                 *  structure. If this is the root window of the window's screen, then the protocol is finished and
441:                 *  there is no further interaction. If it is a window other than the root window, then the protocol
442:                 *  continues with the new parent acting as the embedder window."
443:                 */
444:                XToolkit.awtLock();
445:                try {
446:                    XlibWrapper.XUnmapWindow(XToolkit.getDisplay(),
447:                            xembed.handle);
448:                    XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
449:                            xembed.handle, XToolkit.getDefaultRootWindow(), 0,
450:                            0);
451:                } finally {
452:                    XToolkit.awtUnlock();
453:                }
454:                endDispatching();
455:                xembed.handle = 0;
456:            }
457:
458:            public void windowGainedFocus(WindowEvent e) {
459:                applicationActive = true;
460:                if (isXEmbedActive()) {
461:                    xembedLog.fine("Sending WINDOW_ACTIVATE");
462:                    xembed.sendMessage(xembed.handle, XEMBED_WINDOW_ACTIVATE);
463:                }
464:            }
465:
466:            public void windowLostFocus(WindowEvent e) {
467:                applicationActive = false;
468:                if (isXEmbedActive()) {
469:                    xembedLog.fine("Sending WINDOW_DEACTIVATE");
470:                    xembed.sendMessage(xembed.handle, XEMBED_WINDOW_DEACTIVATE);
471:                }
472:            }
473:
474:            void canvasFocusGained(FocusEvent e) {
475:                if (isXEmbedActive()) {
476:                    xembedLog.fine("Forwarding FOCUS_GAINED");
477:                    int flavor = XEMBED_FOCUS_CURRENT;
478:                    if (e instanceof  CausedFocusEvent) {
479:                        CausedFocusEvent ce = (CausedFocusEvent) e;
480:                        if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) {
481:                            flavor = XEMBED_FOCUS_FIRST;
482:                        } else if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) {
483:                            flavor = XEMBED_FOCUS_LAST;
484:                        }
485:                    }
486:                    xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN, flavor,
487:                            0, 0);
488:                }
489:            }
490:
491:            void canvasFocusLost(FocusEvent e) {
492:                if (isXEmbedActive() && !e.isTemporary()) {
493:                    xembedLog.fine("Forwarding FOCUS_LOST");
494:                    int num = 0;
495:                    if (AccessController.doPrivileged(new GetBooleanAction(
496:                            "sun.awt.xembed.testing"))) {
497:                        Component opp = e.getOppositeComponent();
498:                        try {
499:                            num = Integer.parseInt(opp.getName());
500:                        } catch (NumberFormatException nfe) {
501:                        }
502:                    }
503:                    xembed.sendMessage(xembed.handle, XEMBED_FOCUS_OUT, num, 0,
504:                            0);
505:                }
506:            }
507:
508:            static Field bdataField;
509:
510:            static byte[] getBData(KeyEvent e) {
511:                try {
512:                    if (bdataField == null) {
513:                        bdataField = SunToolkit.getField(
514:                                java.awt.AWTEvent.class, "bdata");
515:                    }
516:                    return (byte[]) bdataField.get(e);
517:                } catch (IllegalAccessException ex) {
518:                    return null;
519:                }
520:            }
521:
522:            void forwardKeyEvent(KeyEvent e) {
523:                xembedLog.fine("Try to forward key event");
524:                byte[] bdata = getBData(e);
525:                long data = Native.toData(bdata);
526:                if (data == 0) {
527:                    return;
528:                }
529:                try {
530:                    XKeyEvent ke = new XKeyEvent(data);
531:                    ke.set_window(xembed.handle);
532:                    if (xembedLog.isLoggable(Level.FINE))
533:                        xembedLog.fine("Forwarding native key event: " + ke);
534:                    XToolkit.awtLock();
535:                    try {
536:                        XlibWrapper.XSendEvent(XToolkit.getDisplay(),
537:                                xembed.handle, false, XlibWrapper.NoEventMask,
538:                                data);
539:                    } finally {
540:                        XToolkit.awtUnlock();
541:                    }
542:                } finally {
543:                    XlibWrapper.unsafe.freeMemory(data);
544:                }
545:            }
546:
547:            /**
548:             * Grab/ungrab key functionality is an unofficial API supported by
549:             * GTK.  Unfortunately, it doesn't support accelerator API, so,
550:             * since this is the ONLY shortcut-processing API available, we
551:             * must support it.  See XEmbed.NON_STANDARD_XEMBED_GTK_*
552:             * messages.  The format of these messages is as follows:
553:             * - request from client:
554:             * data[1] = NON_STANDARD_XEMBED_GTK_GRAB_KEY or NON_STANDARD_XEMBED_GTK_UNGRAB_KEY
555:             * data[3] = X keysym
556:             * data[4] = X modifiers
557:             *
558:             * - response from server (in case the grabbed key has been pressed):
559:             * forwarded XKeyEvent that matches keysym/modifiers pair
560:             */
561:            void grabKey(final long keysym, final long modifiers) {
562:                postEvent(new InvocationEvent(target, new Runnable() {
563:                    public void run() {
564:                        GrabbedKey grab = new GrabbedKey(keysym, modifiers);
565:                        if (xembedLog.isLoggable(Level.FINE))
566:                            xembedLog.fine("Grabbing key: " + grab);
567:                        synchronized (GRAB_LOCK) {
568:                            grabbed_keys.add(grab);
569:                        }
570:                    }
571:                }));
572:            }
573:
574:            void ungrabKey(final long keysym, final long modifiers) {
575:                postEvent(new InvocationEvent(target, new Runnable() {
576:                    public void run() {
577:                        GrabbedKey grab = new GrabbedKey(keysym, modifiers);
578:                        if (xembedLog.isLoggable(Level.FINE))
579:                            xembedLog.fine("UnGrabbing key: " + grab);
580:                        synchronized (GRAB_LOCK) {
581:                            grabbed_keys.remove(grab);
582:                        }
583:                    }
584:                }));
585:            }
586:
587:            void registerAccelerator(final long accel_id, final long keysym,
588:                    final long modifiers) {
589:                postEvent(new InvocationEvent(target, new Runnable() {
590:                    public void run() {
591:                        AWTKeyStroke stroke = xembed.getKeyStrokeForKeySym(
592:                                keysym, modifiers);
593:                        if (stroke != null) {
594:                            if (xembedLog.isLoggable(Level.FINE))
595:                                xembedLog.fine("Registering accelerator "
596:                                        + accel_id + " for " + stroke);
597:                            synchronized (ACCEL_LOCK) {
598:                                accelerators.put(accel_id, stroke);
599:                                accel_lookup.put(stroke, accel_id);
600:                            }
601:                        }
602:                        propogateRegisterAccelerator(stroke);
603:                    }
604:                }));
605:            }
606:
607:            void unregisterAccelerator(final long accel_id) {
608:                postEvent(new InvocationEvent(target, new Runnable() {
609:                    public void run() {
610:                        AWTKeyStroke stroke = null;
611:                        synchronized (ACCEL_LOCK) {
612:                            stroke = accelerators.get(accel_id);
613:                            if (stroke != null) {
614:                                if (xembedLog.isLoggable(Level.FINE))
615:                                    xembedLog
616:                                            .fine("Unregistering accelerator: "
617:                                                    + accel_id);
618:                                accelerators.remove(accel_id);
619:                                accel_lookup.remove(stroke); // FIXME: How about several accelerators with the same stroke?
620:                            }
621:                        }
622:                        propogateUnRegisterAccelerator(stroke);
623:                    }
624:                }));
625:            }
626:
627:            void propogateRegisterAccelerator(AWTKeyStroke stroke) {
628:                // Find the top-level and see if it is XEmbed client. If so, ask him to
629:                // register the accelerator
630:                XWindowPeer parent = getToplevelXWindow();
631:                if (parent != null && parent instanceof  XEmbeddedFramePeer) {
632:                    XEmbeddedFramePeer embedded = (XEmbeddedFramePeer) parent;
633:                    embedded.registerAccelerator(stroke);
634:                }
635:            }
636:
637:            void propogateUnRegisterAccelerator(AWTKeyStroke stroke) {
638:                // Find the top-level and see if it is XEmbed client. If so, ask him to
639:                // register the accelerator
640:                XWindowPeer parent = getToplevelXWindow();
641:                if (parent != null && parent instanceof  XEmbeddedFramePeer) {
642:                    XEmbeddedFramePeer embedded = (XEmbeddedFramePeer) parent;
643:                    embedded.unregisterAccelerator(stroke);
644:                }
645:            }
646:
647:            public boolean postProcessKeyEvent(KeyEvent e) {
648:                // Processing events only if we are in the focused window but
649:                // we are not focus owner since otherwise we will get
650:                // duplicate shortcut events in the client - one is from
651:                // activate_accelerator, another from forwarded event
652:                // FIXME: This is probably an incompatibility, protocol
653:                // doesn't say anything about disable accelerators when client
654:                // is focused.
655:
656:                XWindowPeer parent = getToplevelXWindow();
657:                if (parent == null
658:                        || !((Window) parent.getTarget()).isFocused()
659:                        || target.isFocusOwner()) {
660:                    return false;
661:                }
662:
663:                boolean result = false;
664:
665:                if (xembedLog.isLoggable(Level.FINER))
666:                    xembedLog.finer("Post-processing event " + e);
667:
668:                // Process ACCELERATORS
669:                AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
670:                long accel_id = 0;
671:                boolean exists = false;
672:                synchronized (ACCEL_LOCK) {
673:                    exists = accel_lookup.containsKey(stroke);
674:                    if (exists) {
675:                        accel_id = accel_lookup.get(stroke).longValue();
676:                    }
677:                }
678:                if (exists) {
679:                    if (xembedLog.isLoggable(Level.FINE))
680:                        xembedLog.fine("Activating accelerator " + accel_id);
681:                    xembed.sendMessage(xembed.handle,
682:                            XEMBED_ACTIVATE_ACCELERATOR, accel_id, 0, 0); // FIXME: How about overloaded?
683:                    result = true;
684:                }
685:
686:                // Process Grabs, unofficial GTK feature
687:                exists = false;
688:                GrabbedKey key = new GrabbedKey(e);
689:                synchronized (GRAB_LOCK) {
690:                    exists = grabbed_keys.contains(key);
691:                }
692:                if (exists) {
693:                    if (xembedLog.isLoggable(Level.FINE))
694:                        xembedLog.fine("Forwarding grabbed key " + e);
695:                    forwardKeyEvent(e);
696:                    result = true;
697:                }
698:
699:                return result;
700:            }
701:
702:            public void modalityPushed(ModalityEvent ev) {
703:                xembed.sendMessage(xembed.handle, XEMBED_MODALITY_ON);
704:            }
705:
706:            public void modalityPopped(ModalityEvent ev) {
707:                xembed.sendMessage(xembed.handle, XEMBED_MODALITY_OFF);
708:            }
709:
710:            public void handleClientMessage(XEvent xev) {
711:                super .handleClientMessage(xev);
712:                XClientMessageEvent msg = xev.get_xclient();
713:                if (xembedLog.isLoggable(Level.FINER))
714:                    xembedLog.finer("Client message to embedder: " + msg);
715:                if (msg.get_message_type() == xembed.XEmbed.getAtom()) {
716:                    if (xembedLog.isLoggable(Level.FINE))
717:                        xembedLog.fine(xembed.XEmbedMessageToString(msg));
718:                }
719:                if (isXEmbedActive()) {
720:                    switch ((int) msg.get_data(1)) {
721:                    case _SUN_XEMBED_START:
722:                        // Child has finished initialization and waits for notify
723:                        xembed.processXEmbedInfo();
724:
725:                        notifyChildEmbedded();
726:                        break;
727:                    case XEMBED_REQUEST_FOCUS:
728:                        requestXEmbedFocus();
729:                        break;
730:                    case XEMBED_FOCUS_NEXT:
731:                        focusNext();
732:                        break;
733:                    case XEMBED_FOCUS_PREV:
734:                        focusPrev();
735:                        break;
736:                    case XEMBED_REGISTER_ACCELERATOR:
737:                        registerAccelerator(msg.get_data(2), msg.get_data(3),
738:                                msg.get_data(4));
739:                        break;
740:                    case XEMBED_UNREGISTER_ACCELERATOR:
741:                        unregisterAccelerator(msg.get_data(2));
742:                        break;
743:                    case NON_STANDARD_XEMBED_GTK_GRAB_KEY:
744:                        grabKey(msg.get_data(3), msg.get_data(4));
745:                        break;
746:                    case NON_STANDARD_XEMBED_GTK_UNGRAB_KEY:
747:                        ungrabKey(msg.get_data(3), msg.get_data(4));
748:                        break;
749:                    }
750:                } else {
751:                    xembedLog.finer("But XEmbed is not Active!");
752:                }
753:            }
754:
755:            private static class XEmbedDropTarget extends DropTarget {
756:                public void addDropTargetListener(DropTargetListener dtl)
757:                        throws TooManyListenersException {
758:                    // Drop target listeners registered with this target will never be
759:                    // notified, since all drag notifications are routed to the XEmbed
760:                    // client. To avoid confusion we prohibit listeners registration
761:                    // by throwing TooManyListenersException as if there is a listener
762:                    // registered with this target already.
763:                    throw new TooManyListenersException();
764:                }
765:            }
766:
767:            public void setXEmbedDropTarget() {
768:                // Register a drop site on the top level.
769:                Runnable r = new Runnable() {
770:                    public void run() {
771:                        target.setDropTarget(new XEmbedDropTarget());
772:                    }
773:                };
774:                SunToolkit.executeOnEventHandlerThread(target, r);
775:            }
776:
777:            public void removeXEmbedDropTarget() {
778:                // Unregister a drop site on the top level.
779:                Runnable r = new Runnable() {
780:                    public void run() {
781:                        if (target.getDropTarget() instanceof  XEmbedDropTarget) {
782:                            target.setDropTarget(null);
783:                        }
784:                    }
785:                };
786:                SunToolkit.executeOnEventHandlerThread(target, r);
787:            }
788:
789:            public boolean processXEmbedDnDEvent(long ctxt, int eventID) {
790:                if (xembedLog.isLoggable(Level.FINEST)) {
791:                    xembedLog.finest("     Drop target="
792:                            + target.getDropTarget());
793:                }
794:                if (target.getDropTarget() instanceof  XEmbedDropTarget) {
795:                    AppContext appContext = XToolkit
796:                            .targetToAppContext(getTarget());
797:                    XDropTargetContextPeer peer = XDropTargetContextPeer
798:                            .getPeer(appContext);
799:                    peer.forwardEventToEmbedded(xembed.handle, ctxt, eventID);
800:                    return true;
801:                } else {
802:                    return false;
803:                }
804:            }
805:
806:            class XEmbedServer extends XEmbedHelper implements  XEventDispatcher {
807:                long handle; // Handle to XEmbed client
808:                long version;
809:                long flags;
810:
811:                boolean processXEmbedInfo() {
812:                    long xembed_info_data = Native.allocateLongArray(2);
813:                    try {
814:                        if (!XEmbedInfo
815:                                .getAtomData(handle, xembed_info_data, 2)) {
816:                            // No more XEMBED_INFO? This is not XEmbed client!
817:                            // Unfortunately this is the initial state of the most clients
818:                            // FIXME: add 5-state processing
819:                            //childDestroyed();
820:                            xembedLog
821:                                    .finer("Unable to get XEMBED_INFO atom data");
822:                            return false;
823:                        }
824:                        version = Native.getCard32(xembed_info_data, 0);
825:                        flags = Native.getCard32(xembed_info_data, 1);
826:                        boolean new_mapped = (flags & XEMBED_MAPPED) != 0;
827:                        boolean currently_mapped = XlibUtil
828:                                .getWindowMapState(handle) != XlibWrapper.IsUnmapped;
829:                        if (new_mapped != currently_mapped) {
830:                            if (xembedLog.isLoggable(Level.FINER))
831:                                xembedLog
832:                                        .fine("Mapping state of the client has changed, old state: "
833:                                                + currently_mapped
834:                                                + ", new state: " + new_mapped);
835:                            if (new_mapped) {
836:                                XToolkit.awtLock();
837:                                try {
838:                                    XlibWrapper.XMapWindow(XToolkit
839:                                            .getDisplay(), handle);
840:                                } finally {
841:                                    XToolkit.awtUnlock();
842:                                }
843:                            } else {
844:                                XToolkit.awtLock();
845:                                try {
846:                                    XlibWrapper.XUnmapWindow(XToolkit
847:                                            .getDisplay(), handle);
848:                                } finally {
849:                                    XToolkit.awtUnlock();
850:                                }
851:                            }
852:                        } else {
853:                            xembedLog
854:                                    .finer("Mapping state didn't change, mapped: "
855:                                            + currently_mapped);
856:                        }
857:                        return true;
858:                    } finally {
859:                        XlibWrapper.unsafe.freeMemory(xembed_info_data);
860:                    }
861:                }
862:
863:                public void handlePropertyNotify(XEvent xev) {
864:                    if (isXEmbedActive()) {
865:                        XPropertyEvent ev = xev.get_xproperty();
866:                        if (xembedLog.isLoggable(Level.FINER))
867:                            xembedLog.finer("Property change on client: " + ev);
868:                        if (ev.get_atom() == XAtom.XA_WM_NORMAL_HINTS) {
869:                            childResized();
870:                        } else if (ev.get_atom() == XEmbedInfo.getAtom()) {
871:                            processXEmbedInfo();
872:                        } else if (ev.get_atom() == XDnDConstants.XA_XdndAware
873:                                .getAtom()) {
874:                            XDropTargetRegistry.getRegistry()
875:                                    .unregisterXEmbedClient(getWindow(),
876:                                            xembed.handle);
877:                            if (ev.get_state() == XConstants.PropertyNewValue) {
878:                                XDropTargetRegistry.getRegistry()
879:                                        .registerXEmbedClient(getWindow(),
880:                                                xembed.handle);
881:                            }
882:                        }
883:                    } else {
884:                        xembedLog.finer("XEmbed is not active");
885:                    }
886:                }
887:
888:                void handleConfigureNotify(XEvent xev) {
889:                    if (isXEmbedActive()) {
890:                        XConfigureEvent ev = xev.get_xconfigure();
891:                        if (xembedLog.isLoggable(Level.FINER))
892:                            xembedLog.finer("Bounds change on client: " + ev);
893:                        if (xev.get_xany().get_window() == handle) {
894:                            childResized();
895:                        }
896:                    }
897:                }
898:
899:                public void dispatchEvent(XEvent xev) {
900:                    int type = xev.get_type();
901:                    switch (type) {
902:                    case PropertyNotify:
903:                        handlePropertyNotify(xev);
904:                        break;
905:                    case ConfigureNotify:
906:                        handleConfigureNotify(xev);
907:                        break;
908:                    case ClientMessage:
909:                        handleClientMessage(xev);
910:                        break;
911:                    }
912:                }
913:            }
914:
915:            static class GrabbedKey {
916:                long keysym;
917:                long modifiers;
918:
919:                GrabbedKey(long keysym, long modifiers) {
920:                    this .keysym = keysym;
921:                    this .modifiers = modifiers;
922:                }
923:
924:                GrabbedKey(KeyEvent ev) {
925:                    init(ev);
926:                }
927:
928:                private void init(KeyEvent e) {
929:                    byte[] bdata = getBData(e);
930:                    long data = Native.toData(bdata);
931:                    if (data == 0) {
932:                        return;
933:                    }
934:                    try {
935:                        XToolkit.awtLock();
936:                        try {
937:                            keysym = XWindow.getKeySymForAWTKeyCode(e
938:                                    .getKeyCode());
939:                        } finally {
940:                            XToolkit.awtUnlock();
941:                        }
942:                        XKeyEvent ke = new XKeyEvent(data);
943:
944:                        // We recognize only these masks
945:                        modifiers = ke.get_state()
946:                                & (ShiftMask | ControlMask | LockMask);
947:                        if (xembedLog.isLoggable(Level.FINEST))
948:                            xembedLog.finest("Mapped " + e + " to " + this );
949:                    } finally {
950:                        XlibWrapper.unsafe.freeMemory(data);
951:                    }
952:                }
953:
954:                public int hashCode() {
955:                    return (int) keysym & 0xFFFFFFFF;
956:                }
957:
958:                public boolean equals(Object o) {
959:                    if (!(o instanceof  GrabbedKey)) {
960:                        return false;
961:                    }
962:                    GrabbedKey key = (GrabbedKey) o;
963:                    return (keysym == key.keysym && modifiers == key.modifiers);
964:                }
965:
966:                public String toString() {
967:                    return "Key combination[keysym=" + keysym + ", mods="
968:                            + modifiers + "]";
969:                }
970:            }
971:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.