--- a/jdk/src/solaris/native/sun/awt/awt_dnd_dt.c Wed Jul 05 16:40:31 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3700 +0,0 @@
-/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#ifdef HEADLESS
- #error This file should not be included in headless library
-#endif
-
-#include "awt_dnd.h"
-
-#include "jlong.h"
-
-#include "awt_DataTransferer.h"
-#include "awt_MToolkit.h"
-
-#include "java_awt_dnd_DnDConstants.h"
-#include "java_awt_event_MouseEvent.h"
-
-#include "sun_awt_motif_MComponentPeer.h"
-#include "awt_xembed.h"
-
-#define DT_INITIAL_STATE 0
-#define DT_ENTERED_STATE 1
-#define DT_OVER_STATE 2
-
-extern struct ComponentIDs componentIDs;
-extern struct MComponentPeerIDs mComponentPeerIDs;
-
-/**************************** XEmbed server DnD support ***********************/
-extern void
-set_xembed_drop_target(JNIEnv* env, jobject server);
-extern void
-remove_xembed_drop_target(JNIEnv* env, jobject server);
-extern Boolean
-is_xembed_client(Window window);
-
-DECLARE_JAVA_CLASS(MEmbedCanvasPeerClass, "sun/awt/motif/MEmbedCanvasPeer");
-/******************************************************************************/
-
-typedef enum {
- EventSuccess, /* Event is successfully processed. */
- EventFailure /* Failed to process the event. */
-} EventStatus;
-
-typedef enum {
- EnterEvent, /* XdndEnter, TOP_LEVEL_ENTER */
- MotionEvent, /* XdndPosition, DRAG_MOTION, OPERATION_CHANGED */
- LeaveEvent, /* XdndLeave, TOP_LEVEL_LEAVE */
- DropEvent, /* XdndDrop, DROP_START */
- UnknownEvent
-} EventType;
-
-static Protocol source_protocol = NO_PROTOCOL;
-static unsigned int source_protocol_version = 0;
-static Window source_window = None;
-static Atom source_atom = None;
-static long source_window_mask = None;
-static jint source_actions = java_awt_dnd_DnDConstants_ACTION_NONE;
-/*
- * According to XDnD protocol, XdndActionList is optional.
- * In case if XdndActionList is not set on the source, the list of drop actions
- * supported by the source is constructed as follows:
- * - "copy" is always included;
- * - "move" is included if at least one XdndPosition message received
- * after the latest XdndEnter passed XdndActionMove in data.l[4];
- * - "link" is included if at least one XdndPosition message received
- * after the latest XdndEnter passed XdndActionLink in data.l[4].
- * We use a boolean flag to signal that we are building the list of drop actions
- * supported by the source.
- */
-static Boolean track_source_actions = False;
-static jint user_action = java_awt_dnd_DnDConstants_ACTION_NONE;
-static jlongArray source_data_types = NULL;
-static Atom* source_data_types_native = NULL;
-static unsigned int source_data_types_count = 0;
-static int source_x = 0;
-static int source_y = 0;
-static jobject target_component = NULL;
-/*
- * The Motif DnD protocol prescribes that DROP_START message should always be
- * preceeded with TOP_LEVEL_LEAVE message. We need to cleanup on TOP_LEVEL_LEAVE
- * message, but DROP_START wouldn't be processed properly.
- * To resolve this issue we postpone cleanup using a boolean flag this flag is
- * set when we receive the TOP_LEVEL_LEAVE message and cleared when the next
- * client message arrives if that message is not DROP_START. If that message is
- * a DROP_START message, the flag is cleared after the DROP_START is processed.
- */
-static Boolean motif_top_level_leave_postponed = False;
-/*
- * We store a postponed TOP_LEVEL_LEAVE message here.
- */
-static XClientMessageEvent motif_top_level_leave_postponed_event;
-
-/* Forward declarations */
-static Window get_root_for_window(Window window);
-static Window get_outer_canvas_for_window(Window window);
-static Boolean register_drop_site(Widget outer_canvas, XtPointer componentRef);
-static Boolean is_xdnd_drag_message_type(unsigned long message_type);
-static Boolean register_xdnd_drop_site(Display* dpy, Window toplevel,
- Window window);
-
-/**************************** JNI stuff ***************************************/
-
-DECLARE_JAVA_CLASS(dtcp_clazz, "sun/awt/motif/X11DropTargetContextPeer")
-
-static void
-dt_postDropTargetEvent(JNIEnv* env, jobject component, int x, int y,
- jint dropAction, jint event_id,
- XClientMessageEvent* event) {
- DECLARE_STATIC_VOID_JAVA_METHOD(dtcp_postDropTargetEventToPeer, dtcp_clazz,
- "postDropTargetEventToPeer",
- "(Ljava/awt/Component;IIII[JJI)V");
-
- {
- void* copy = NULL;
-
- if (event != NULL) {
- /*
- * For XDnD messages we append the information from the latest
- * XdndEnter to the context. It is done to be able to reconstruct
- * XdndEnter for an XEmbed client.
- */
- Boolean isXDnDMessage =
- is_xdnd_drag_message_type(event->message_type);
-
- if (isXDnDMessage) {
- copy = malloc(sizeof(XClientMessageEvent) +
- 4 * sizeof(long));
- } else {
- copy = malloc(sizeof(XClientMessageEvent));
- }
-
- if (copy == NULL) {
- DTRACE_PRINTLN2("%s:%d malloc failed.", __FILE__, __LINE__);
- return;
- }
-
- memcpy(copy, event, sizeof(XClientMessageEvent));
-
- if (isXDnDMessage) {
- size_t msgSize = sizeof(XClientMessageEvent);
- long data1 = source_protocol_version << XDND_PROTOCOL_SHIFT;
- long * appended_data;
- if (source_data_types_native != NULL &&
- source_data_types_count > 3) {
-
- data1 |= XDND_DATA_TYPES_BIT;
- }
-
- appended_data = (long*)((char*)copy + msgSize);
- appended_data[0] = data1;
- appended_data[1] = source_data_types_count > 0 ?
- source_data_types_native[0] : 0;
- appended_data[2] = source_data_types_count > 1 ?
- source_data_types_native[1] : 0;
- appended_data[3] = source_data_types_count > 2 ?
- source_data_types_native[2] : 0;
- }
- }
-
- DASSERT(!JNU_IsNull(env, component));
-
- (*env)->CallStaticVoidMethod(env, clazz, dtcp_postDropTargetEventToPeer,
- component, x, y, dropAction,
- source_actions, source_data_types,
- ptr_to_jlong(copy), event_id);
- }
-}
-
-/******************************************************************************/
-
-/********************* Embedded drop site list support ************************/
-
-struct EmbeddedDropSiteListEntryRec;
-
-typedef struct EmbeddedDropSiteListEntryRec EmbeddedDropSiteListEntry;
-
-struct EmbeddedDropSiteListEntryRec {
- Window toplevel;
- Window root;
- /*
- * We select for PropertyNotify events on the toplevel, so we need to
- * restore the event mask when we are done with this toplevel.
- */
- long event_mask;
- unsigned int embedded_sites_count;
- Window* embedded_sites;
- EmbeddedDropSiteListEntry* next;
-};
-
-static EmbeddedDropSiteListEntry* embedded_drop_site_list = NULL;
-
-struct EmbeddedDropSiteProtocolListEntryRec;
-
-typedef struct EmbeddedDropSiteProtocolListEntryRec EmbeddedDropSiteProtocolListEntry;
-
-struct EmbeddedDropSiteProtocolListEntryRec {
- Window window;
- Window proxy;
- /*
- * We override the XdndAware property on the toplevel, so we should keep its
- * original contents - the XDnD protocol version supported by the browser.
- * This is needed to adjust XDnD messages forwarded to the browser.
- */
- unsigned int protocol_version;
- /* True if the toplevel was already registered as a drag receiver and
- we just changed the proxy. False, otherwise */
- Boolean overriden;
- EmbeddedDropSiteProtocolListEntry* next;
-};
-
-static EmbeddedDropSiteProtocolListEntry* embedded_motif_protocol_list = NULL;
-static EmbeddedDropSiteProtocolListEntry* embedded_xdnd_protocol_list = NULL;
-
-typedef enum {
- RegFailure, /* Proxy registration failed */
- RegSuccess, /* The new drop site is registered with the new proxy */
- RegOverride, /* The new proxy is set for the existing drop site */
- RegAlreadyRegistered /* This proxy is already set for this drop site */
-} ProxyRegistrationStatus;
-
-/* Forward declarations. */
-static EmbeddedDropSiteProtocolListEntry*
-get_xdnd_protocol_entry_for_toplevel(Window toplevel);
-static EmbeddedDropSiteProtocolListEntry*
-get_motif_protocol_entry_for_toplevel(Window toplevel);
-static void remove_xdnd_protocol_entry_for_toplevel(Window toplevel);
-static void remove_motif_protocol_entry_for_toplevel(Window toplevel);
-
-/*
- * Registers the toplevel as a Motif drag receiver if it is not registered yet,
- * sets the specified new_proxy for it and returns the previous proxy in old_proxy.
- * Does nothing if the new_proxy is already set as a proxy for this toplevel.
- * Returns the completion status.
- */
-static ProxyRegistrationStatus
-set_motif_proxy(Display* dpy, Window toplevel, Window new_proxy, Window *old_proxy) {
- Boolean override = False;
-
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char* data;
- unsigned char ret;
-
- DASSERT(old_proxy != NULL);
-
- *old_proxy = None;
-
- data = NULL;
- ret = checked_XGetWindowProperty(dpy, toplevel,
- _XA_MOTIF_DRAG_RECEIVER_INFO, 0, 0xFFFF,
- False, AnyPropertyType, &type, &format,
- &nitems, &after, &data);
-
- /* Check if toplevel is a valid window. */
- if (ret != Success) {
- return RegFailure;
- }
-
- if (ret == Success && data != NULL && type != None && format == 8
- && nitems >= MOTIF_RECEIVER_INFO_SIZE) {
- unsigned char byte_order = read_card8((char*)data, 0);
- void* p = (char*)data + 4;
-
- /* Browser and plugin have different byte orders - report failure for now. */
- if (MOTIF_BYTE_ORDER != byte_order) {
- XFree(data);
- return RegFailure;
- }
-
- *old_proxy = read_card32((char*)data, 4, byte_order);
-
- /* If the proxy is already set to the specified window - return. */
- if (*old_proxy == new_proxy) {
- XFree(data);
- return RegAlreadyRegistered;
- }
-
- /* replace the proxy window */
- write_card32(&p, new_proxy);
-
- override = True;
- } else {
- void* p;
-
- if (ret == Success) {
- XFree(data);
- data = NULL;
- }
-
- data = malloc(MOTIF_RECEIVER_INFO_SIZE);
-
- if (data == NULL) {
- DTRACE_PRINTLN2("%s:%d malloc failed.", __FILE__, __LINE__);
- return RegFailure;
- }
-
- p = data;
-
- write_card8(&p, MOTIF_BYTE_ORDER);
- write_card8(&p, MOTIF_DND_PROTOCOL_VERSION); /* protocol version */
- write_card8(&p, MOTIF_DYNAMIC_STYLE); /* protocol style */
- write_card8(&p, 0); /* pad */
- write_card32(&p, new_proxy); /* proxy window */
- write_card16(&p, 0); /* num_drop_sites */
- write_card16(&p, 0); /* pad */
- write_card32(&p, MOTIF_RECEIVER_INFO_SIZE);
- }
-
- ret = checked_XChangeProperty(dpy, toplevel,
- _XA_MOTIF_DRAG_RECEIVER_INFO,
- _XA_MOTIF_DRAG_RECEIVER_INFO, 8,
- PropModeReplace, (unsigned char*)data,
- MOTIF_RECEIVER_INFO_SIZE);
-
- if (data != NULL) {
- XFree(data);
- data = NULL;
- }
-
- if (ret == Success) {
- if (override) {
- return RegOverride;
- } else {
- return RegSuccess;
- }
- } else {
- return RegFailure;
- }
-}
-
-/*
- * Registers the toplevel as a XDnD drag receiver if it is not registered yet,
- * sets the specified new_proxy for it and returns the previous proxy in
- * old_proxy and the original XDnD protocol version in old_version.
- * Does nothing if the new_proxy is already set as a proxy for this toplevel.
- * Returns the completion status.
- */
-static ProxyRegistrationStatus
-set_xdnd_proxy(Display* dpy, Window toplevel, Window new_proxy,
- Window* old_proxy, unsigned int* old_version) {
- Atom version_atom = XDND_PROTOCOL_VERSION;
- Window xdnd_proxy = None;
- Boolean override = False;
-
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char* data;
- unsigned char ret;
-
- DASSERT(old_proxy != NULL);
-
- *old_proxy = None;
-
- data = NULL;
- ret = checked_XGetWindowProperty(dpy, toplevel, XA_XdndAware, 0, 1,
- False, AnyPropertyType, &type, &format,
- &nitems, &after, &data);
-
- if (ret != Success) {
- return RegFailure;
- }
-
- if (ret == Success && data != NULL && type == XA_ATOM) {
- unsigned int protocol_version = *((unsigned int*)data);
-
- override = True;
- *old_version = protocol_version;
-
- /* XdndProxy is not supported for prior to XDnD version 4 */
- if (protocol_version >= 4) {
- int status;
-
- XFree(data);
-
- data = NULL;
- status = XGetWindowProperty(dpy, toplevel, XA_XdndProxy, 0, 1,
- False, XA_WINDOW, &type, &format,
- &nitems, &after, &data);
-
- if (status == Success && data != NULL && type == XA_WINDOW) {
- xdnd_proxy = *((Window*)data);
-
- if (xdnd_proxy != None) {
- XFree(data);
-
- data = NULL;
- status = XGetWindowProperty(dpy, xdnd_proxy, XA_XdndProxy,
- 0, 1, False, XA_WINDOW, &type,
- &format, &nitems, &after, &data);
-
- if (status != Success || data == NULL || type != XA_WINDOW ||
- *((Window*)data) != xdnd_proxy) {
- /* Ignore invalid proxy. */
- xdnd_proxy = None;
- }
- }
-
- if (xdnd_proxy != None) {
- XFree(data);
-
- data = NULL;
- status = XGetWindowProperty(dpy, xdnd_proxy, XA_XdndAware,
- 0, 1, False, AnyPropertyType,
- &type, &format, &nitems, &after,
- &data);
-
- if (status == Success && data != NULL && type == XA_ATOM) {
- unsigned int proxy_version = *((unsigned int*)data);
-
- if (proxy_version != protocol_version) {
- /* Ignore invalid proxy. */
- xdnd_proxy = None;
- }
- } else {
- /* Ignore invalid proxy. */
- xdnd_proxy = None;
- }
- }
- }
-
- *old_proxy = xdnd_proxy;
- }
- }
-
- XFree(data);
-
- /* If the proxy is already set to the specified window - return. */
- if (xdnd_proxy == new_proxy) {
- return RegAlreadyRegistered;
- }
-
- /* The proxy window must have the XdndAware set, as XDnD protocol prescribes
- to check the proxy window for XdndAware. */
- ret = checked_XChangeProperty(dpy, new_proxy, XA_XdndAware, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char*)&version_atom, 1);
-
- if (ret != Success) {
- return RegFailure;
- }
-
- /* The proxy window must have the XdndProxy set to point to itself. */
- ret = checked_XChangeProperty(dpy, new_proxy, XA_XdndProxy, XA_WINDOW, 32,
- PropModeReplace,
- (unsigned char*)&new_proxy, 1);
-
- if (ret != Success) {
- return RegFailure;
- }
-
- ret = checked_XChangeProperty(dpy, toplevel, XA_XdndAware, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char*)&version_atom, 1);
-
- if (ret != Success) {
- return RegFailure;
- }
-
- ret = checked_XChangeProperty(dpy, toplevel, XA_XdndProxy, XA_WINDOW, 32,
- PropModeReplace,
- (unsigned char*)&new_proxy, 1);
-
- if (ret == Success) {
- if (override) {
- return RegOverride;
- } else {
- return RegSuccess;
- }
- } else {
- return RegFailure;
- }
-}
-
-/*
- * 'toplevel' is the browser toplevel window. To register a drop site on the
- * plugin window we set the proxy for the browser toplevel window to point to
- * the awt_root_shell window.
- *
- * We assume that only one JVM per browser instance is possible. This
- * assumption is true with the current plugin implementation - it creates a
- * single JVM for all plugin instances created by the given plugin factory.
- *
- * When a client message event for the browser toplevel window is received, we
- * will iterate over drop sites registered with this toplevel and determine if
- * the mouse pointer is currently over one of them (there could be several
- * plugin windows in one browser window - for example if an HTML page contains
- * frames and several frames contain a plugin object).
- *
- * If the pointer is not over any of the plugin drop sites the client message
- * will be resent to the browser, otherwise it will be processed normally.
- */
-static EmbeddedDropSiteListEntry*
-awt_dnd_dt_init_proxy(Display* dpy, Window root, Window toplevel, Window window) {
- Window awt_root_window = get_awt_root_window();
- Window motif_proxy = None;
- Boolean motif_override = False;
- unsigned long event_mask = 0;
-
- if (awt_root_window == None) {
- return NULL;
- }
-
- /* Grab server, since we are working with the window that belongs to
- another client. REMIND: ungrab when done!!! */
- XGrabServer(dpy);
-
- {
- ProxyRegistrationStatus motif_status = RegFailure;
-
- motif_status = set_motif_proxy(dpy, toplevel, awt_root_window, &motif_proxy);
-
- switch (motif_status) {
- case RegFailure:
- case RegAlreadyRegistered:
- XUngrabServer(dpy);
- /* Workaround for bug 5039226 */
- XSync(dpy, False);
- return NULL;
- case RegOverride:
- motif_override = True;
- break;
- case RegSuccess:
- motif_override = False;
- break;
- default:
- DASSERT(False);
- }
-
-
- }
-
- {
- XWindowAttributes xwa;
- XGetWindowAttributes(dpy, toplevel, &xwa);
- event_mask = xwa.your_event_mask;
- if ((event_mask & PropertyChangeMask) == 0) {
- XSelectInput(dpy, toplevel, event_mask | PropertyChangeMask);
- }
- }
-
- XUngrabServer(dpy);
- /* Workaround for bug 5039226 */
- XSync(dpy, False);
-
- /* Add protocol specific entries for the toplevel. */
- {
- EmbeddedDropSiteProtocolListEntry* motif_entry = NULL;
-
- motif_entry = malloc(sizeof(EmbeddedDropSiteProtocolListEntry));
-
- if (motif_entry == NULL) {
- return NULL;
- }
-
- motif_entry->window = toplevel;
- motif_entry->proxy = motif_proxy;
- motif_entry->protocol_version = 0;
- motif_entry->overriden = motif_override;
- motif_entry->next = embedded_motif_protocol_list;
- embedded_motif_protocol_list = motif_entry;
- }
-
- {
- EmbeddedDropSiteListEntry* entry = NULL;
- Window* sites = NULL;
-
- entry = malloc(sizeof(EmbeddedDropSiteListEntry));
-
- if (entry == NULL) {
- return NULL;
- }
-
- sites = malloc(sizeof(Window));
-
- if (sites == NULL) {
- free(entry);
- return NULL;
- }
-
- sites[0] = window;
-
- entry->toplevel = toplevel;
- entry->root = root;
- entry->event_mask = event_mask;
- entry->embedded_sites_count = 1;
- entry->embedded_sites = sites;
- entry->next = NULL;
-
- return entry;
- }
-}
-
-static void
-register_xdnd_embedder(Display* dpy, EmbeddedDropSiteListEntry* entry, long window) {
- Window awt_root_window = get_awt_root_window();
- Window toplevel = entry->toplevel;
- Window xdnd_proxy = None;
- unsigned int xdnd_protocol_version = 0;
- Boolean xdnd_override = False;
- Boolean register_xdnd = True;
- Boolean motif_overriden = False;
-
- EmbeddedDropSiteProtocolListEntry* motif_entry = embedded_motif_protocol_list;
- while (motif_entry != NULL) {
- if (motif_entry->window == toplevel) {
- motif_overriden = motif_entry->overriden;
- break;
- }
- motif_entry = motif_entry->next;
- }
-
- /*
- * First check if the window is an XEmbed client.
- * In this case we don't have to setup a proxy on the toplevel,
- * instead we register the XDnD drop site on the embedded window.
- */
- if (isXEmbedActiveByWindow(window)) {
- register_xdnd_drop_site(dpy, toplevel, window);
- return;
- }
-
- /*
- * By default, we register a drop site that supports both dnd
- * protocols. This approach is not appropriate in plugin
- * scenario if the browser doesn't support XDnD. If we forcibly set
- * XdndAware on the browser toplevel, any drag source that supports both
- * protocols and prefers XDnD will be unable to drop anything on the
- * browser.
- * The solution for this problem is not to register XDnD drop site
- * if the browser supports only Motif DnD.
- */
- if (motif_overriden) {
- int status;
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char* data;
-
- data = NULL;
- status = XGetWindowProperty(dpy, toplevel, XA_XdndAware, 0, 1,
- False, AnyPropertyType, &type, &format,
- &nitems, &after, &data);
-
- XFree(data);
- data = NULL;
-
- if (type != XA_ATOM) {
- register_xdnd = False;
- }
- }
-
- if (register_xdnd) {
- ProxyRegistrationStatus xdnd_status;
- /* Grab server, since we are working with the window that belongs to
- another client. REMIND: ungrab when done!!! */
- XGrabServer(dpy);
-
- xdnd_status =
- set_xdnd_proxy(dpy, toplevel, awt_root_window, &xdnd_proxy,
- &xdnd_protocol_version);
-
- XUngrabServer(dpy);
-
- switch (xdnd_status) {
- case RegFailure:
- case RegAlreadyRegistered:
- return;
- case RegOverride:
- xdnd_override = True;
- break;
- case RegSuccess:
- xdnd_override = False;
- break;
- default:
- DASSERT(False);
- }
-
- {
- EmbeddedDropSiteProtocolListEntry* xdnd_entry = NULL;
-
- xdnd_entry = malloc(sizeof(EmbeddedDropSiteProtocolListEntry));
-
- if (xdnd_entry == NULL) {
- return;
- }
-
- xdnd_entry->window = toplevel;
- xdnd_entry->proxy = xdnd_proxy;
- xdnd_entry->protocol_version = xdnd_protocol_version;
- xdnd_entry->overriden = xdnd_override;
- xdnd_entry->next = embedded_xdnd_protocol_list;
- embedded_xdnd_protocol_list = xdnd_entry;
- }
- }
-}
-
-/*
- * If embedded_drop_site_list already contains an entry with the specified
- * 'toplevel', the method registers the specified 'window' as an embedded drop
- * site for this 'toplevel' and returns True.
- * Otherwise, it checks if the 'toplevel' is a registered drop site for adds
- * (window, component) pair to the list and returns True
- * if completes successfully.
- */
-static Boolean
-add_to_embedded_drop_site_list(Display* dpy, Window root, Window toplevel,
- Window window) {
- EmbeddedDropSiteListEntry* entry = embedded_drop_site_list;
-
- while (entry != NULL) {
- if (entry->toplevel == toplevel) {
- void* p = realloc(entry->embedded_sites,
- sizeof(Window) *
- (entry->embedded_sites_count + 1));
- if (p == NULL) {
- return False;
- }
- entry->embedded_sites = p;
- entry->embedded_sites[entry->embedded_sites_count++] = window;
-
- register_xdnd_embedder(dpy, entry, window);
-
- return True;
- }
- entry = entry->next;
- }
-
- entry = awt_dnd_dt_init_proxy(dpy, root, toplevel, window);
-
- if (entry == NULL) {
- return False;
- }
-
- register_xdnd_embedder(dpy, entry, window);
-
- entry->next = embedded_drop_site_list;
- embedded_drop_site_list = entry;
-
- return True;
-}
-
-/*
- * Removes the window from the list of embedded drop sites for the toplevel.
- * Returns True if the window was successfully removed, False otherwise.
- */
-static Boolean
-remove_from_embedded_drop_site_list(Display* dpy, Window toplevel, Window window) {
- EmbeddedDropSiteListEntry* entry = embedded_drop_site_list;
- EmbeddedDropSiteListEntry* prev = NULL;
-
- while (entry != NULL) {
- if (entry->toplevel == toplevel) {
- unsigned int idx;
-
- for (idx = 0; idx < entry->embedded_sites_count; idx++) {
- if (entry->embedded_sites[idx] == window) {
- int tail = entry->embedded_sites_count - idx - 1;
- if (tail > 0) {
- memmove(entry->embedded_sites + idx,
- entry->embedded_sites + idx + 1,
- tail * sizeof(Window));
- }
- entry->embedded_sites_count--;
-
- /* If the list of embedded drop sites for this toplevel
- becomes empty - restore the original proxies and remove
- the entry. */
- if (entry->embedded_sites_count == 0) {
- Widget w = XtWindowToWidget(dpy, toplevel);
-
- if (w != NULL) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- Widget copy = w;
- jobject peer = findPeer(&w);
-
- if (!JNU_IsNull(env, peer) &&
- (*env)->IsInstanceOf(env, peer,
- get_MEmbedCanvasPeerClass(env)) == JNI_TRUE) {
- remove_xembed_drop_target(env, peer);
- }
- } else {
- EmbeddedDropSiteProtocolListEntry* xdnd_entry =
- get_xdnd_protocol_entry_for_toplevel(toplevel);
- EmbeddedDropSiteProtocolListEntry* motif_entry =
- get_motif_protocol_entry_for_toplevel(toplevel);
-
- if (xdnd_entry != NULL) {
- if (xdnd_entry->overriden == True) {
- XChangeProperty(dpy, toplevel, XA_XdndAware,
- XA_ATOM, 32,
- PropModeReplace,
- (unsigned char*)&xdnd_entry->protocol_version,
- 1);
-
- XChangeProperty(dpy, toplevel, XA_XdndProxy,
- XA_WINDOW, 32,
- PropModeReplace,
- (unsigned char*)&xdnd_entry->proxy, 1);
- } else {
- XDeleteProperty(dpy, toplevel, XA_XdndAware);
- XDeleteProperty(dpy, toplevel, XA_XdndProxy);
- }
- remove_xdnd_protocol_entry_for_toplevel(toplevel);
- }
-
- if (motif_entry != NULL) {
- if (motif_entry->overriden == True) {
- /* Request status */
- int status;
-
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char* data;
-
- data = NULL;
- status = XGetWindowProperty(dpy, toplevel,
- _XA_MOTIF_DRAG_RECEIVER_INFO, 0, 0xFFFF,
- False, AnyPropertyType, &type, &format,
- &nitems, &after, &data);
-
- if (status == Success && data != NULL && type != None &&
- format == 8 && nitems >= MOTIF_RECEIVER_INFO_SIZE) {
- unsigned char byte_order = read_card8((char*)data, 0);
- void* p = (char*)data + 4;
-
- DASSERT(MOTIF_BYTE_ORDER == byte_order);
-
- if (MOTIF_BYTE_ORDER == byte_order) {
- /* restore the original proxy window */
- write_card32(&p, motif_entry->proxy);
-
- XChangeProperty(dpy, toplevel,
- _XA_MOTIF_DRAG_RECEIVER_INFO,
- _XA_MOTIF_DRAG_RECEIVER_INFO, 8,
- PropModeReplace,
- (unsigned char*)data,
- MOTIF_RECEIVER_INFO_SIZE);
- }
- }
-
- if (status == Success) {
- XFree(data);
- }
- } else {
- XDeleteProperty(dpy, toplevel, _XA_MOTIF_DRAG_RECEIVER_INFO);
- }
-
- remove_motif_protocol_entry_for_toplevel(toplevel);
- }
-
- if ((entry->event_mask & PropertyChangeMask) == 0) {
- XSelectInput(dpy, toplevel, entry->event_mask);
- }
- }
-
- if (prev == NULL) {
- embedded_drop_site_list = entry->next;
- } else {
- prev->next = entry->next;
- }
-
- free(entry);
- }
- return True;
- }
- }
- return False;
- }
- prev = entry;
- entry = entry->next;
- }
- return False;
-}
-
-static EmbeddedDropSiteListEntry*
-get_entry_for_toplevel(Window toplevel) {
- EmbeddedDropSiteListEntry* entry = embedded_drop_site_list;
-
- while (entry != NULL) {
- if (entry->toplevel == toplevel) {
- return entry;
- }
- entry = entry->next;
- }
- return NULL;
-}
-
-static EmbeddedDropSiteProtocolListEntry*
-get_motif_protocol_entry_for_toplevel(Window toplevel) {
- EmbeddedDropSiteProtocolListEntry* entry = embedded_motif_protocol_list;
-
- while (entry != NULL) {
- if (entry->window == toplevel) {
- return entry;
- }
- entry = entry->next;
- }
- return NULL;
-}
-
-static EmbeddedDropSiteProtocolListEntry*
-get_xdnd_protocol_entry_for_toplevel(Window toplevel) {
- EmbeddedDropSiteProtocolListEntry* entry = embedded_xdnd_protocol_list;
-
- while (entry != NULL) {
- if (entry->window == toplevel) {
- return entry;
- }
- entry = entry->next;
- }
- return NULL;
-}
-
-static void
-remove_motif_protocol_entry_for_toplevel(Window toplevel) {
- EmbeddedDropSiteProtocolListEntry* entry = embedded_motif_protocol_list;
- EmbeddedDropSiteProtocolListEntry* prev_entry = NULL;
-
- while (entry != NULL) {
- if (entry->window == toplevel) {
- if (prev_entry != NULL) {
- prev_entry->next = entry->next;
- } else {
- embedded_motif_protocol_list = entry->next;
- }
- free(entry);
- }
- entry = entry->next;
- prev_entry = entry;
- }
-}
-
-static void
-remove_xdnd_protocol_entry_for_toplevel(Window toplevel) {
- EmbeddedDropSiteProtocolListEntry* entry = embedded_xdnd_protocol_list;
- EmbeddedDropSiteProtocolListEntry* prev_entry = NULL;
-
- while (entry != NULL) {
- if (entry->window == toplevel) {
- if (prev_entry != NULL) {
- prev_entry->next = entry->next;
- } else {
- embedded_xdnd_protocol_list = entry->next;
- }
- free(entry);
- }
- entry = entry->next;
- }
-}
-
-static Boolean
-is_embedding_toplevel(Window toplevel) {
- return get_entry_for_toplevel(toplevel) != NULL;
-}
-
-static Window
-get_embedded_window(Display* dpy, Window toplevel, int x, int y) {
- EmbeddedDropSiteListEntry* entry = get_entry_for_toplevel(toplevel);
-
- if (entry != NULL) {
- unsigned int idx;
-
- for (idx = 0; idx < entry->embedded_sites_count; idx++) {
- Window site = entry->embedded_sites[idx];
- Window child = None;
- int x_return, y_return;
-
- if (XTranslateCoordinates(dpy, entry->root, site, x, y,
- &x_return, &y_return, &child)) {
- if (x_return >= 0 && y_return >= 0) {
- XWindowAttributes xwa;
- XGetWindowAttributes(dpy, site, &xwa);
- if (xwa.map_state != IsUnmapped &&
- x_return < xwa.width && y_return < xwa.height) {
- return site;
- }
- }
- }
- }
- }
-
- return None;
-}
-
-/*
- * If the toplevel is not an embedding toplevel does nothing and returns False.
- * Otherwise, sets xdnd_proxy for the specified toplevel to the 'proxy_window',
- * xdnd_protocol_version to 'version', xdnd_override to 'override', returns True.
- */
-static Boolean
-set_xdnd_proxy_for_toplevel(Window toplevel, Window proxy_window,
- unsigned int version, Boolean override) {
- EmbeddedDropSiteProtocolListEntry* entry =
- get_xdnd_protocol_entry_for_toplevel(toplevel);
-
- if (entry == NULL) {
- return False;
- }
-
- entry->proxy = proxy_window;
- entry->protocol_version = version;
- entry->overriden = override;
-
- return True;
-}
-
-/*
- * If the toplevel is not an embedding toplevel does nothing and returns False.
- * Otherwise, sets motif_proxy for the specified toplevel to the proxy_window,
- * motif_override to 'override' and returns True.
- */
-static Boolean
-set_motif_proxy_for_toplevel(Window toplevel, Window proxy_window, Boolean override) {
- EmbeddedDropSiteProtocolListEntry* entry =
- get_motif_protocol_entry_for_toplevel(toplevel);
-
- if (entry == NULL) {
- return False;
- }
-
- entry->proxy = proxy_window;
- entry->overriden = override;
-
- return True;
-}
-
-/*
- * Forwards a drag notification to the embedding toplevel modifying the event
- * to match the protocol version supported by the toplevel.
- * Returns True if the event is sent, False otherwise.
- */
-static Boolean
-forward_client_message_to_toplevel(Window toplevel, XClientMessageEvent* event) {
- EmbeddedDropSiteProtocolListEntry* protocol_entry = NULL;
- Window proxy = None;
-
- if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
- protocol_entry = get_motif_protocol_entry_for_toplevel(toplevel);
- } else {
- /* Assume XDnD */
- protocol_entry = get_xdnd_protocol_entry_for_toplevel(toplevel);
- if (protocol_entry != NULL) {
- /* Adjust the event to match the XDnD protocol version. */
- unsigned int version = protocol_entry->protocol_version;
- if (event->message_type == XA_XdndEnter) {
- unsigned int min_version = source_protocol_version < version ?
- source_protocol_version : version;
- event->data.l[1] = min_version << XDND_PROTOCOL_SHIFT;
- event->data.l[1] |= source_data_types_count > 3 ? XDND_DATA_TYPES_BIT : 0;
- }
- }
- }
-
- if (protocol_entry == NULL) {
- return False;
- }
-
- if (!protocol_entry->overriden) {
- return False;
- }
- proxy = protocol_entry->proxy;
-
- if (proxy == None) {
- proxy = toplevel;
- }
-
- event->window = toplevel;
-
- XSendEvent(event->display, proxy, False, NoEventMask, (XEvent*)event);
-
- return True;
-}
-
-/******************************************************************************/
-
-/********************* Drop site list support *********************************/
-
-struct DropSiteListEntryRec;
-
-typedef struct DropSiteListEntryRec DropSiteListEntry;
-
-struct DropSiteListEntryRec {
- Window window;
- Window root;
- /*
- * The closest to the root ancestor with WM_STATE property set.
- * Normally toplevel == window.
- * In plugin scenario toplevel is the browser toplevel window.
- */
- Window toplevel;
- /*
- * Java top-level position is the outer canvas position, not the shell
- * window position. We need to keep the outer canvas ID (and the root ID) to
- * translate from mouse position root coordinates to the Java component
- * coordinates.
- */
- Window outer_canvas;
- jobject component;
- DropSiteListEntry* next;
-};
-
-static DropSiteListEntry* drop_site_list = NULL;
-
-/*
- * If drop_site_list already contains an entry with the same window,
- * does nothing and returns False.
- * Otherwise, adds a new entry the list and returns True
- * if completes successfully.
- */
-static Boolean
-add_to_drop_site_list(Window window, Window root, Window toplevel,
- Window outer_canvas, jobject component) {
- DropSiteListEntry* entry = drop_site_list;
-
- while (entry != NULL) {
- if (entry->window == window) {
- return False;
- }
- entry = entry->next;
- }
-
- entry = malloc(sizeof(DropSiteListEntry));
-
- if (entry == NULL) {
- return False;
- }
-
- entry->window = window;
- entry->root = root;
- entry->toplevel = toplevel;
- entry->outer_canvas = outer_canvas;
- entry->component = component;
- entry->next = drop_site_list;
- drop_site_list = entry;
-
- return True;
-}
-
-/*
- * Returns True if the list entry for the specified window has been successfully
- * removed from the list. Otherwise, returns False.
- */
-static Boolean
-remove_from_drop_site_list(Window window) {
- DropSiteListEntry* entry = drop_site_list;
- DropSiteListEntry* prev = NULL;
-
- while (entry != NULL) {
- if (entry->window == window) {
- if (prev != NULL) {
- prev->next = entry->next;
- } else {
- drop_site_list = entry->next;
- }
- free(entry);
- return True;
- }
- prev = entry;
- entry = entry->next;
- }
-
- return False;
-}
-
-static jobject
-get_component_for_window(Window window) {
- DropSiteListEntry* entry = drop_site_list;
-
- while (entry != NULL) {
- if (entry->window == window) {
- return entry->component;
- }
- entry = entry->next;
- }
-
- return NULL;
-}
-
-static Window
-get_root_for_window(Window window) {
- DropSiteListEntry* entry = drop_site_list;
-
- while (entry != NULL) {
- if (entry->window == window) {
- return entry->root;
- }
- entry = entry->next;
- }
-
- return None;
-}
-
-static Window
-get_toplevel_for_window(Window window) {
- DropSiteListEntry* entry = drop_site_list;
-
- while (entry != NULL) {
- if (entry->window == window) {
- return entry->toplevel;
- }
- entry = entry->next;
- }
-
- return None;
-}
-
-static Window
-get_outer_canvas_for_window(Window window) {
- DropSiteListEntry* entry = drop_site_list;
-
- while (entry != NULL) {
- if (entry->window == window) {
- return entry->outer_canvas;
- }
- entry = entry->next;
- }
-
- return None;
-}
-/******************************************************************************/
-
-/******************* Delayed drop site registration stuff *********************/
-struct DelayedRegistrationEntryRec;
-
-typedef struct DelayedRegistrationEntryRec DelayedRegistrationEntry;
-
-struct DelayedRegistrationEntryRec {
- Widget outer_canvas;
- jobject component;
- XtIntervalId timer;
- DelayedRegistrationEntry* next;
-};
-
-static DelayedRegistrationEntry* delayed_registration_list = NULL;
-
-static const int DELAYED_REGISTRATION_PERIOD = 500;
-
-/* Timer callback. */
-static void
-register_drop_site_later(XtPointer client_data, XtIntervalId* id);
-
-/*
- * Enqueues the specified widget and component for delayed drop site
- * registration. If this widget has already been registered, does nothing and
- * returns False. Otherwise, schedules a timer callback that will repeatedly
- * attempt to register the drop site until the registration succeeds.
- * To remove this widget from the queue of delayed registration call
- * remove_delayed_registration_entry().
- *
- * The caller must own AWT_LOCK.
- */
-static Boolean
-add_delayed_registration_entry(Widget outer_canvas, XtPointer componentRef) {
- DelayedRegistrationEntry* entry = delayed_registration_list;
-
- if (outer_canvas == NULL || componentRef == NULL) {
- return False;
- }
-
- while (entry != NULL && entry->outer_canvas != outer_canvas) {
- entry = entry->next;
- }
-
- if (entry != NULL) {
- return False;
- }
-
- entry = malloc(sizeof(DelayedRegistrationEntry));
-
- if (entry == NULL) {
- return False;
- }
-
- entry->outer_canvas = outer_canvas;
- entry->component = componentRef;
- entry->timer = XtAppAddTimeOut(awt_appContext, DELAYED_REGISTRATION_PERIOD,
- register_drop_site_later, entry);
- entry->next = delayed_registration_list;
- delayed_registration_list = entry;
-
- return True;
-}
-
-/*
- * Unregisters the timer callback and removes this widget from the queue of
- * delayed drop site registration.
- *
- * The caller must own AWT_LOCK.
- */
-static Boolean
-remove_delayed_registration_entry(Widget outer_canvas) {
- DelayedRegistrationEntry* entry = delayed_registration_list;
- DelayedRegistrationEntry* prev = NULL;
-
- if (outer_canvas == NULL) {
- return False;
- }
-
- while (entry != NULL && entry->outer_canvas != outer_canvas) {
- prev = entry;
- entry = entry->next;
- }
-
- if (entry == NULL) {
- return False;
- }
-
- if (prev != NULL) {
- prev->next = entry->next;
- } else {
- delayed_registration_list = entry->next;
- }
-
- if (entry->timer) {
- XtRemoveTimeOut(entry->timer);
- entry->timer = (XtIntervalId)0;
- }
-
- free(entry);
-
- return True;
-}
-
-static void
-register_drop_site_later(XtPointer client_data, XtIntervalId* id) {
- DelayedRegistrationEntry* entry = (DelayedRegistrationEntry*)client_data;
-
- if (XtIsRealized(entry->outer_canvas) &&
- register_drop_site(entry->outer_canvas, entry->component)) {
- remove_delayed_registration_entry(entry->outer_canvas);
- } else {
- entry->timer = XtAppAddTimeOut(awt_appContext, DELAYED_REGISTRATION_PERIOD,
- register_drop_site_later, entry);
- }
-}
-/******************************************************************************/
-
-static void
-awt_dnd_cleanup() {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
-
- if (!JNU_IsNull(env, target_component)) {
- /* Trigger dragExit */
- /*
- * Note: we pass NULL native context. This indicates that response
- * shouldn't be sent to the source.
- */
- dt_postDropTargetEvent(env, target_component, 0, 0,
- java_awt_dnd_DnDConstants_ACTION_NONE,
- java_awt_event_MouseEvent_MOUSE_EXITED,
- NULL);
- }
-
- if (motif_top_level_leave_postponed) {
- XClientMessageEvent* leave = &motif_top_level_leave_postponed_event;
- if (leave->type == ClientMessage) {
- Window win = leave->window;
- if (is_embedding_toplevel(win)) {
- forward_client_message_to_toplevel(win, leave);
- }
- }
- }
-
- if (source_window != None) {
- XSelectInput(awt_display, source_window, source_window_mask);
- }
-
- source_protocol = NO_PROTOCOL;
- source_protocol_version = 0;
- source_window = None;
- source_atom = None;
- source_window_mask = 0;
- source_actions = java_awt_dnd_DnDConstants_ACTION_NONE;
- track_source_actions = False;
- (*env)->DeleteGlobalRef(env, source_data_types);
- source_data_types = NULL;
- if (source_data_types_native != NULL) {
- free(source_data_types_native);
- source_data_types_native = NULL;
- }
- source_data_types_count = 0;
- source_x = 0;
- source_y = 0;
- target_component = NULL;
- motif_top_level_leave_postponed = False;
- memset(&motif_top_level_leave_postponed_event, 0,
- sizeof(XClientMessageEvent));
-}
-
-static jlongArray
-get_data_types_array(JNIEnv* env, Atom* types, unsigned int types_count) {
- jlongArray array = NULL;
- jboolean isCopy;
- jlong* jTargets;
-#ifndef _LP64 /* Atom and jlong are different sizes in the 32-bit build */
- unsigned int i;
-#endif
-
- if ((*env)->PushLocalFrame(env, 1) < 0) {
- return NULL;
- }
-
- array = (*env)->NewLongArray(env, types_count);
-
- if (JNU_IsNull(env, array)) {
- return NULL;
- }
-
- if (types_count == 0) {
- return array;
- }
-
- jTargets = (*env)->GetLongArrayElements(env, array, &isCopy);
- if (jTargets == NULL) {
- (*env)->PopLocalFrame(env, NULL);
- return NULL;
- }
-
-#ifdef _LP64
- memcpy(jTargets, types, types_count * sizeof(Atom));
-#else
- for (i = 0; i < types_count; i++) {
- jTargets[i] = (types[i] & 0xFFFFFFFFLU);
- }
-#endif
-
- (*env)->ReleaseLongArrayElements(env, array, jTargets, 0);
-
- array = (*env)->NewGlobalRef(env, array);
-
- (*env)->PopLocalFrame(env, NULL);
-
- return array;
-}
-
-static Boolean
-is_xdnd_drag_message_type(unsigned long message_type) {
- return message_type == XA_XdndEnter ||
- message_type == XA_XdndPosition ||
- message_type == XA_XdndLeave ||
- message_type == XA_XdndDrop ? True : False;
-}
-
-/*
- * Returns EventConsume if the event should be consumed,
- * EventPassAlong otherwise.
- */
-static EventStatus
-handle_xdnd_enter(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- Display* dpy = event->display;
- long* event_data = event->data.l;
- Window source_win = None;
- long source_win_mask = 0;
- unsigned int protocol_version = 0;
- unsigned int data_types_count = 0;
- Atom* data_types = NULL;
- jlongArray java_data_types = NULL;
- jint actions = java_awt_dnd_DnDConstants_ACTION_NONE;
- Boolean track = False;
-
- DTRACE_PRINTLN5("%s:%d XdndEnter comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (!JNU_IsNull(env, target_component) || source_window != None ||
- source_protocol != NO_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- /*
- * NOTE: the component can be NULL if the event was sent to the embedding
- * toplevel.
- */
- if (JNU_IsNull(env, get_component_for_window(event->window)) &&
- !is_embedding_toplevel(event->window)) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - window is not a registered drop site.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- protocol_version =
- (event_data[1] & XDND_PROTOCOL_MASK) >> XDND_PROTOCOL_SHIFT;
-
- /* XDnD compliance only requires supporting version 3 and up. */
- if (protocol_version < XDND_MIN_PROTOCOL_VERSION) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid protocol version.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- /* Ignore the source if the protocol version is higher than we support. */
- if (protocol_version > XDND_PROTOCOL_VERSION) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid protocol version.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- source_win = event_data[0];
-
- /* Extract the list of supported actions. */
- if (protocol_version < 2) {
- /* Prior to XDnD version 2 only COPY action was supported. */
- actions = java_awt_dnd_DnDConstants_ACTION_COPY;
- } else {
- unsigned char ret;
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char *data;
-
- data = NULL;
- ret = checked_XGetWindowProperty(dpy, source_win, XA_XdndActionList,
- 0, 0xFFFF, False, XA_ATOM, &type,
- &format, &nitems, &after, &data);
-
- /* Ignore the source if the window is destroyed. */
- if (ret == BadWindow) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid window.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- if (ret == Success) {
- if (type == XA_ATOM && format == 32) {
- unsigned int i;
- Atom* action_atoms = (Atom*)data;
-
- for (i = 0; i < nitems; i++) {
- actions |= xdnd_to_java_action(action_atoms[i]);
- }
- }
-
- /*
- * According to XDnD protocol, XdndActionList is optional.
- * If XdndActionList is not set we try to guess which actions are
- * supported.
- */
- if (type == None) {
- actions = java_awt_dnd_DnDConstants_ACTION_COPY;
- track = True;
- }
-
- XFree(data);
- }
- }
-
- /* Extract the available data types. */
- if (event_data[1] & XDND_DATA_TYPES_BIT) {
- unsigned char ret;
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char *data;
-
- data = NULL;
- ret = checked_XGetWindowProperty(dpy, source_win, XA_XdndTypeList,
- 0, 0xFFFF, False, XA_ATOM, &type,
- &format, &nitems, &after, &data);
-
- /* Ignore the source if the window is destroyed. */
- if (ret == BadWindow) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid window.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- if (ret == Success) {
- if (type == XA_ATOM && format == 32 && nitems > 0) {
- data_types_count = nitems;
- data_types = (Atom*)malloc(data_types_count * sizeof(Atom));
-
- if (data_types == NULL) {
- XFree(data);
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - malloc fails.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- memcpy((void *)data_types, (void *)data,
- data_types_count * sizeof(Atom));
- }
-
- XFree(data);
- }
- } else {
- int i;
- data_types = (Atom*)malloc(3 * sizeof (Atom));
- if (data_types == NULL) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - malloc fails.",
- __FILE__, __LINE__);
- return EventFailure;
- }
- for (i = 0; i < 3; i++) {
- Atom j;
- if ((j = event_data[2 + i]) != None) {
- data_types[data_types_count++] = j;
- }
- }
- }
-
- java_data_types = get_data_types_array(env, data_types, data_types_count);
-
- if (JNU_IsNull(env, java_data_types)) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - cannot create types array.",
- __FILE__, __LINE__);
- free((char*)data_types);
- return EventFailure;
- }
-
- /*
- * Select for StructureNotifyMask to receive DestroyNotify in case of source
- * crash.
- */
- {
- unsigned char ret;
- XWindowAttributes xwa;
-
- XGetWindowAttributes(dpy, source_win, &xwa);
-
- source_win_mask = xwa.your_event_mask;
-
- ret = checked_XSelectInput(dpy, source_win,
- (source_win_mask | StructureNotifyMask));
-
- if (ret == BadWindow) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid window.",
- __FILE__, __LINE__);
- free((char*)data_types);
- (*env)->DeleteGlobalRef(env, java_data_types);
- return EventFailure;
- }
- }
-
- /* Update the global state. */
- source_protocol = XDND_PROTOCOL;
- source_protocol_version = protocol_version;
- source_window = source_win;
- source_window_mask = source_win_mask;
- source_actions = actions;
- track_source_actions = track;
- source_data_types = java_data_types;
- source_data_types_native = data_types;
- source_data_types_count = data_types_count;
-
- DTRACE_PRINTLN5("%s:%d XdndEnter handled src_win=%ld protocol=%d fmt=%d.",
- __FILE__, __LINE__,
- source_window, source_protocol, data_types_count);
-
- return EventSuccess;
-}
-
-/*
- * Returns EventConsume if the event should be consumed,
- * EventPassAlong otherwise.
- */
-static EventStatus
-handle_xdnd_position(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- long* event_data = event->data.l;
- Window source_win = None;
- Time time_stamp = CurrentTime;
- Atom action_atom = None;
- jint action = java_awt_dnd_DnDConstants_ACTION_NONE;
- int x = 0;
- int y = 0;
- jint java_event_id = 0;
- jobject component = NULL;
- Window receiver = None;
-
- DTRACE_PRINTLN5("%s:%d XdndPosition comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (source_protocol != XDND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d XdndPosition rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- source_win = event_data[0];
-
- /* Ignore XDnD messages from all other windows. */
- if (source_window != source_win) {
- DTRACE_PRINTLN4("%s:%d XdndPosition rejected - invalid source window cur=%ld this=%ld.",
- __FILE__, __LINE__, source_window, source_win);
- return EventFailure;
- }
-
- x = event_data[2] >> 16;
- y = event_data[2] & 0xFFFF;
-
- component = get_component_for_window(event->window);
-
- if (JNU_IsNull(env, component)) {
- /*
- * The window must be the embedding toplevel, since otherwise we would reject the
- * XdndEnter and never get to this point.
- */
- DASSERT(is_embedding_toplevel(event->window));
-
- receiver = get_embedded_window(event->display, event->window, x, y);
-
- if (receiver != None) {
- component = get_component_for_window(receiver);
- }
- } else {
- receiver = event->window;
- }
-
- /* Translate mouse position from root coordinates
- to the target window coordinates. */
- if (receiver != None) {
- Window child = None;
- XTranslateCoordinates(event->display,
- get_root_for_window(receiver),
- get_outer_canvas_for_window(receiver),
- x, y, &x, &y, &child);
- }
-
- /* Time stamp - new in XDnD version 1. */
- if (source_protocol_version > 0) {
- time_stamp = event_data[3];
- }
-
- /* User action - new in XDnD version 1. */
- if (source_protocol_version > 1) {
- action_atom = event_data[4];
- } else {
- /* The default action is XdndActionCopy */
- action_atom = XA_XdndActionCopy;
- }
-
- action = xdnd_to_java_action(action_atom);
-
- if (track_source_actions) {
- source_actions |= action;
- }
-
- if (JNU_IsNull(env, component)) {
- if (!JNU_IsNull(env, target_component)) {
- dt_postDropTargetEvent(env, target_component, x, y,
- java_awt_dnd_DnDConstants_ACTION_NONE,
- java_awt_event_MouseEvent_MOUSE_EXITED,
- NULL);
- }
- } else {
- if (JNU_IsNull(env, target_component)) {
- java_event_id = java_awt_event_MouseEvent_MOUSE_ENTERED;
- } else {
- java_event_id = java_awt_event_MouseEvent_MOUSE_DRAGGED;
- }
-
- dt_postDropTargetEvent(env, component, x, y, action,
- java_event_id, event);
- }
-
- user_action = action;
- source_x = x;
- source_y = y;
- target_component = component;
-
- return EventSuccess;
-}
-
-/*
- * Returns EventConsume if the event should be consumed,
- * EventPassAlong otherwise.
- */
-static EventStatus
-handle_xdnd_leave(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- long* event_data = event->data.l;
- Window source_win = None;
-
- if (source_protocol != XDND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d XdndLeave rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- source_win = event_data[0];
-
- /* Ignore XDnD messages from all other windows. */
- if (source_window != source_win) {
- DTRACE_PRINTLN4("%s:%d XdndLeave rejected - invalid source window cur=%ld this=%ld.",
- __FILE__, __LINE__, source_window, source_win);
- return EventFailure;
- }
-
- awt_dnd_cleanup();
-
- return EventSuccess;
-}
-
-/*
- * Returns EventConsume if the event should be consumed,
- * EventPassAlong otherwise.
- */
-static EventStatus
-handle_xdnd_drop(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- long* event_data = event->data.l;
- Window source_win = None;
-
- DTRACE_PRINTLN5("%s:%d XdndDrop comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (source_protocol != XDND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d XdndDrop rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- source_win = event_data[0];
-
- /* Ignore XDnD messages from all other windows. */
- if (source_window != source_win) {
- DTRACE_PRINTLN4("%s:%d XdndDrop rejected - invalid source window cur=%ld this=%ld.",
- __FILE__, __LINE__, source_window, source_win);
- return EventFailure;
- }
-
- if (!JNU_IsNull(env, target_component)) {
- dt_postDropTargetEvent(env, target_component, source_x, source_y, user_action,
- java_awt_event_MouseEvent_MOUSE_RELEASED, event);
- }
-
- return EventSuccess;
-}
-
-/*
- * Returns EventPassAlong if the event should be passed to the original proxy.
- * TOP_LEVEL_ENTER should be passed to the original proxy only if the event is
- * invalid.
- */
-static EventStatus
-handle_motif_top_level_enter(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- Display* dpy = event->display;
- char* event_data = event->data.b;
- unsigned char event_byte_order = 0;
- Window source_win = None;
- long source_win_mask = 0;
- unsigned int protocol_version = MOTIF_DND_PROTOCOL_VERSION;
- Atom property_atom = None;
- unsigned int data_types_count = 0;
- Atom* data_types = NULL;
- jlongArray java_data_types = NULL;
-
- DTRACE_PRINTLN5("%s:%d TOP_LEVEL_ENTER comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (!JNU_IsNull(env, target_component) || source_window != None ||
- source_protocol != NO_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_ENTER rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- if (JNU_IsNull(env, get_component_for_window(event->window)) &&
- !is_embedding_toplevel(event->window)) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_ENTER rejected - window is not a registered drop site.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- event_byte_order = read_card8(event_data, 1);
- source_win = read_card32(event_data, 8, event_byte_order);
- property_atom = read_card32(event_data, 12, event_byte_order);
-
- /* Extract the available data types. */
- {
- unsigned char ret;
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char *data;
-
- data = NULL;
- ret = checked_XGetWindowProperty(dpy, source_win, property_atom, 0,
- 0xFFFF, False,
- _XA_MOTIF_DRAG_INITIATOR_INFO, &type,
- &format, &nitems, &after, &data);
-
- /* Ignore the source if the window is destroyed. */
- if (ret == BadWindow) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_ENTER rejected - invalid window.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- if (ret == BadAtom) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_ENTER rejected - invalid property atom.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- if (ret == Success) {
- if (type == _XA_MOTIF_DRAG_INITIATOR_INFO && format == 8 &&
- nitems == MOTIF_INITIATOR_INFO_SIZE) {
- unsigned char property_byte_order = read_card8((char*)data, 0);
- int index = read_card16((char*)data, 2, property_byte_order);
-
- protocol_version = read_card8((char*)data, 1);
-
- if (protocol_version > MOTIF_DND_PROTOCOL_VERSION) {
- DTRACE_PRINTLN3("%s:%d TOP_LEVEL_ENTER rejected - invalid protocol version: %d.",
- __FILE__, __LINE__, protocol_version);
- XFree(data);
- return EventFailure;
- }
-
- get_target_list_for_index(dpy, index, &data_types, &data_types_count);
- }
-
- XFree(data);
- }
- }
-
- java_data_types = get_data_types_array(env, data_types, data_types_count);
-
- if (JNU_IsNull(env, java_data_types)) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_ENTER rejected - cannot create types array.",
- __FILE__, __LINE__);
- free((char*)data_types);
- return EventFailure;
- }
-
- /*
- * Select for StructureNotifyMask to receive DestroyNotify in case of source
- * crash.
- */
- {
- unsigned char ret;
- XWindowAttributes xwa;
-
- XGetWindowAttributes(dpy, source_win, &xwa);
-
- source_win_mask = xwa.your_event_mask;
-
- ret = checked_XSelectInput(dpy, source_win,
- (source_win_mask | StructureNotifyMask));
-
- if (ret == BadWindow) {
- DTRACE_PRINTLN2("%s:%d XdndEnter rejected - invalid window.",
- __FILE__, __LINE__);
- free((char*)data_types);
- (*env)->DeleteGlobalRef(env, java_data_types);
- return EventFailure;
- }
- }
-
- source_protocol = MOTIF_DND_PROTOCOL;
- source_protocol_version = protocol_version;
- source_window = source_win;
- source_atom = property_atom;
- source_window_mask = source_win_mask;
- /*
- * TOP_LEVEL_ENTER doesn't communicate the list of supported actions
- * They are provided in DRAG_MOTION.
- */
- source_actions = java_awt_dnd_DnDConstants_ACTION_NONE;
- track_source_actions = False;
- source_data_types = java_data_types;
- source_data_types_native = data_types;
- source_data_types_count = data_types_count;
- DTRACE_PRINTLN6("%s:%d TOP_LEVEL_ENTER comp=%d src_win=%ld protocol=%d fmt=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol, data_types_count);
-
- return EventSuccess;
-}
-
-/*
- * Returns EventPassAlong if the event should be passed to the original proxy.
- * DRAG_MOTION event shouldn't be passed to the original proxy only if it is
- * a valid event and the mouse coordinates passed in it specify the point over
- * a Java component in this JVM.
- */
-static EventStatus
-handle_motif_drag_motion(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- char* event_data = event->data.b;
- unsigned char event_reason = 0;
- unsigned char event_byte_order = 0;
- Window source_win = None;
- CARD16 flags = 0;
- unsigned char motif_action = 0;
- unsigned char motif_actions = 0;
- jint java_action = java_awt_dnd_DnDConstants_ACTION_NONE;
- jint java_actions = java_awt_dnd_DnDConstants_ACTION_NONE;
- int x = 0;
- int y = 0;
- jint java_event_id = 0;
- jobject component = NULL;
-
- DTRACE_PRINTLN5("%s:%d DRAG_MOTION comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (source_protocol != MOTIF_DND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d DRAG_MOTION rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- event_reason = read_card8(event_data, 0) & MOTIF_MESSAGE_REASON_MASK;
- event_byte_order = read_card8(event_data, 1);
-
- flags = read_card16(event_data, 2, event_byte_order);
-
- motif_action = (flags & MOTIF_DND_ACTION_MASK) >> MOTIF_DND_ACTION_SHIFT;
- motif_actions = (flags & MOTIF_DND_ACTIONS_MASK) >> MOTIF_DND_ACTIONS_SHIFT;
-
- java_action = motif_to_java_actions(motif_action);
- java_actions = motif_to_java_actions(motif_actions);
-
- /* Append source window id to the event data, so that we can send the
- response properly. */
- {
- Window win = source_window;
- void* p = &event->data.b[12];
- if (event_byte_order != MOTIF_BYTE_ORDER) {
- SWAP4BYTES(win);
- }
- write_card32(&p, (CARD32)win);
- }
-
- component = get_component_for_window(event->window);
-
- if (event_reason == OPERATION_CHANGED) {
- /* OPERATION_CHANGED event doesn't provide coordinates, so we use
- previously stored position and component ref. */
- x = source_x;
- y = source_y;
-
- if (JNU_IsNull(env, component)) {
- component = target_component;
- }
- } else {
- Window receiver = None;
-
- x = read_card16(event_data, 8, event_byte_order);
- y = read_card16(event_data, 10, event_byte_order);
-
- if (JNU_IsNull(env, component)) {
- /*
- * The window must be the embedding toplevel, since otherwise we
- * would reject the TOP_LEVEL_ENTER and never get to this point.
- */
- DASSERT(is_embedding_toplevel(event->window));
-
- receiver = get_embedded_window(event->display, event->window, x, y);
-
- if (receiver != None) {
- component = get_component_for_window(receiver);
- }
- } else {
- receiver = event->window;
- }
-
- /* Translate mouse position from root coordinates
- to the target window coordinates. */
- if (receiver != None) {
- Window child = None;
- XTranslateCoordinates(event->display,
- get_root_for_window(receiver),
- get_outer_canvas_for_window(receiver),
- x, y, &x, &y, &child);
- }
- }
-
- if (JNU_IsNull(env, component)) {
- if (!JNU_IsNull(env, target_component)) {
- /* Triggers dragExit */
- dt_postDropTargetEvent(env, target_component, x, y,
- java_awt_dnd_DnDConstants_ACTION_NONE,
- java_awt_event_MouseEvent_MOUSE_EXITED,
- NULL);
- }
- } else {
- if (JNU_IsNull(env, target_component)) {
- /* Triggers dragEnter */
- java_event_id = java_awt_event_MouseEvent_MOUSE_ENTERED;
- } else {
- /* Triggers dragOver */
- java_event_id = java_awt_event_MouseEvent_MOUSE_DRAGGED;
- }
-
- dt_postDropTargetEvent(env, component, x, y, java_action, java_event_id,
- event);
- }
-
- source_actions = java_actions;
- track_source_actions = False;
- user_action = java_action;
- source_x = x;
- source_y = y;
- target_component = component;
-
- return EventSuccess;
-}
-
-/*
- * Returns EventPassAlong if the event should be passed to the original proxy.
- * TOP_LEVEL_LEAVE should be passed to the original proxy only if the event
- * is invalid.
- */
-static EventStatus
-handle_motif_top_level_leave(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- char* event_data = event->data.b;
- unsigned char event_byte_order = 0;
- Window source_win = None;
-
- DTRACE_PRINTLN5("%s:%d TOP_LEVEL_LEAVE comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (source_protocol != MOTIF_DND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_LEAVE rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- event_byte_order = read_card8(event_data, 1);
- source_win = read_card32(event_data, 8, event_byte_order);
-
- /* Ignore Motif DnD messages from all other windows. */
- if (source_window != source_win) {
- DTRACE_PRINTLN4("%s:%d TOP_LEVEL_LEAVE rejected - invalid source window cur=%ld this=%ld.",
- __FILE__, __LINE__, source_window, source_win);
- return EventFailure;
- }
-
- /*
- * Postpone upcall to java, so that we can abort it in case
- * if drop immediatelly follows (see BugTraq ID 4395290).
- * Send a dummy ClientMessage event to guarantee that a postponed java
- * upcall will be processed.
- */
- motif_top_level_leave_postponed = True;
- {
- XClientMessageEvent dummy;
- Window proxy;
-
- dummy.display = event->display;
- dummy.type = ClientMessage;
- dummy.window = event->window;
- dummy.format = 32;
- dummy.message_type = None;
-
- /*
- * If this is an embedded drop site, the event should go to the
- * awt_root_window as this is a proxy for all embedded drop sites.
- * Otherwise the event should go to the event->window, as we don't use
- * proxies for normal drop sites.
- */
- if (is_embedding_toplevel(event->window)) {
- proxy = get_awt_root_window();
- } else {
- proxy = event->window;
- }
-
- XSendEvent(event->display, proxy, False, NoEventMask,
- (XEvent*)&dummy);
- }
-
- return EventSuccess;
-}
-
-/*
- * Returns EventPassAlong if the event should be passed to the original proxy.
- * DROP_START event shouldn't be passed to the original proxy only if it is
- * a valid event and the mouse coordinates passed in it specify the point over
- * a Java component in this JVM.
- */
-static EventStatus
-handle_motif_drop_start(XClientMessageEvent* event) {
- JNIEnv *env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- char* event_data = event->data.b;
- unsigned char event_byte_order = 0;
- Window source_win = None;
- Atom property_atom = None;
- CARD16 flags = 0;
- unsigned char motif_action = 0;
- unsigned char motif_actions = 0;
- jint java_action = java_awt_dnd_DnDConstants_ACTION_NONE;
- jint java_actions = java_awt_dnd_DnDConstants_ACTION_NONE;
- int x = 0;
- int y = 0;
- jobject component = NULL;
- Window receiver = None;
-
- DTRACE_PRINTLN5("%s:%d DROP_START comp=%X src_win=%ld protocol=%d.",
- __FILE__, __LINE__,
- target_component, source_window, source_protocol);
-
- if (source_protocol != MOTIF_DND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d DROP_START rejected - invalid state.",
- __FILE__, __LINE__);
- return EventFailure;
- }
-
- event_byte_order = read_card8(event_data, 1);
- source_win = read_card32(event_data, 16, event_byte_order);
-
- /* Ignore Motif DnD messages from all other windows. */
- if (source_window != source_win) {
- DTRACE_PRINTLN4("%s:%d DROP_START rejected - invalid source window cur=%ld this=%ld.",
- __FILE__, __LINE__, source_window, source_win);
- return EventFailure;
- }
-
- property_atom = read_card32(event_data, 12, event_byte_order);
-
- flags = read_card16(event_data, 2, event_byte_order);
-
- motif_action = (flags & MOTIF_DND_ACTION_MASK) >> MOTIF_DND_ACTION_SHIFT;
- motif_actions = (flags & MOTIF_DND_ACTIONS_MASK) >> MOTIF_DND_ACTIONS_SHIFT;
-
- java_action = motif_to_java_actions(motif_action);
- java_actions = motif_to_java_actions(motif_actions);
-
- x = read_card16(event_data, 8, event_byte_order);
- y = read_card16(event_data, 10, event_byte_order);
-
- source_actions = java_actions;
-
- component = get_component_for_window(event->window);
-
- if (JNU_IsNull(env, component)) {
- /*
- * The window must be the embedding toplevel, since otherwise we would reject the
- * TOP_LEVEL_ENTER and never get to this point.
- */
- DASSERT(is_embedding_toplevel(event->window));
-
- receiver = get_embedded_window(event->display, event->window, x, y);
-
- if (receiver != None) {
- component = get_component_for_window(receiver);
- }
- } else {
- receiver = event->window;
- }
-
- /* Translate mouse position from root coordinates
- to the target window coordinates. */
- if (receiver != None) {
- Window child = None;
- XTranslateCoordinates(event->display,
- get_root_for_window(receiver),
- get_outer_canvas_for_window(receiver),
- x, y, &x, &y, &child);
- }
-
- if (JNU_IsNull(env, component)) {
- if (!JNU_IsNull(env, target_component)) {
- /* Triggers dragExit */
- dt_postDropTargetEvent(env, target_component, x, y,
- java_awt_dnd_DnDConstants_ACTION_NONE,
- java_awt_event_MouseEvent_MOUSE_EXITED,
- NULL);
- }
- } else {
- dt_postDropTargetEvent(env, component, x, y, java_action,
- java_awt_event_MouseEvent_MOUSE_RELEASED,
- event);
- }
-
- return EventSuccess;
-}
-
-static void
-send_enter_message_to_toplevel(Window toplevel, XClientMessageEvent* xclient) {
- XClientMessageEvent enter;
-
- if (source_protocol == XDND_PROTOCOL) {
- enter.display = xclient->display;
- enter.type = ClientMessage;
- enter.window = toplevel;
- enter.format = 32;
- enter.message_type = XA_XdndEnter;
- enter.data.l[0] = xclient->data.l[0]; /* XID of the source window */
- enter.data.l[1] = source_protocol_version << XDND_PROTOCOL_SHIFT;
- enter.data.l[1] |= source_data_types_count > 3 ? XDND_DATA_TYPES_BIT : 0;
- enter.data.l[2] =
- source_data_types_count > 0 ? source_data_types_native[0] : None;
- enter.data.l[3] =
- source_data_types_count > 1 ? source_data_types_native[1] : None;
- enter.data.l[4] =
- source_data_types_count > 2 ? source_data_types_native[2] : None;
- } else if (source_protocol == MOTIF_DND_PROTOCOL) {
- int reason = (int)(xclient->data.b[0] & MOTIF_MESSAGE_REASON_MASK);
- unsigned char byte_order = xclient->data.b[1];
-
- enter.display = xclient->display;
- enter.type = ClientMessage;
- enter.window = toplevel;
- enter.format = 8;
- enter.message_type = _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
-
- {
- void* p = &enter.data.b[0];
- int flags = 0;
-
- flags |= java_to_motif_actions(user_action) << MOTIF_DND_ACTION_SHIFT;
- flags |= java_to_motif_actions(source_actions) << MOTIF_DND_ACTIONS_SHIFT;
-
- write_card8(&p, TOP_LEVEL_ENTER | MOTIF_MESSAGE_FROM_INITIATOR);
- write_card8(&p, byte_order);
- write_card16(&p, flags);
- {
- Time time_stamp = read_card32(xclient->data.b, 4, byte_order);
- Window src_window = source_window;
- Atom motif_atom = _XA_MOTIF_ATOM_0;
-
- if (byte_order != MOTIF_BYTE_ORDER) {
- SWAP4BYTES(time_stamp);
- SWAP4BYTES(src_window);
- SWAP4BYTES(motif_atom);
- }
- write_card32(&p, time_stamp);
- write_card32(&p, src_window);
- write_card32(&p, motif_atom);
- }
- }
- } else {
- return;
- }
-
- forward_client_message_to_toplevel(toplevel, &enter);
-}
-
-static void
-send_leave_message_to_toplevel(Window toplevel, XClientMessageEvent* xclient) {
- XClientMessageEvent leave;
-
- if (source_protocol == XDND_PROTOCOL) {
- leave.display = xclient->display;
- leave.type = ClientMessage;
- leave.window = toplevel;
- leave.format = 32;
- leave.message_type = XA_XdndLeave;
- leave.data.l[0] = xclient->data.l[0]; /* XID of the source window */
- leave.data.l[1] = 0; /* flags */
- } else if (source_protocol == MOTIF_DND_PROTOCOL) {
- int reason = (int)(xclient->data.b[0] & MOTIF_MESSAGE_REASON_MASK);
- unsigned char byte_order = xclient->data.b[1];
-
- leave.display = xclient->display;
- leave.type = ClientMessage;
- leave.window = toplevel;
- leave.format = 8;
- leave.message_type = _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
-
- {
- void* p = &leave.data.b[0];
- int flags = 0;
-
- write_card8(&p, TOP_LEVEL_LEAVE | MOTIF_MESSAGE_FROM_INITIATOR);
- write_card8(&p, byte_order);
-
- {
- Time time_stamp = read_card32(xclient->data.b, 4, byte_order);
- Window src_window = source_window;
-
- if (byte_order != MOTIF_BYTE_ORDER) {
- SWAP4BYTES(time_stamp);
- SWAP4BYTES(src_window);
- }
- write_card32(&p, time_stamp);
- write_card32(&p, src_window);
- }
- }
- } else {
- return;
- }
-
- forward_client_message_to_toplevel(toplevel, &leave);
-}
-
-static void
-post_process_client_message(XClientMessageEvent* xclient, EventStatus status,
- EventType type) {
- Window win = xclient->window;
- Boolean postponed_leave = motif_top_level_leave_postponed;
-
- motif_top_level_leave_postponed = False;
-
- if (is_embedding_toplevel(win)) {
- Boolean server_grabbed = False;
-
- if (postponed_leave) {
- XClientMessageEvent* leave = &motif_top_level_leave_postponed_event;
- DASSERT(leave->type == ClientMessage && type == DropEvent);
- /* Grab the server to ensure that no event is sent between
- the TOP_LEVEL_LEAVE and the next message. */
- XGrabServer(awt_display);
- forward_client_message_to_toplevel(leave->window, leave);
- memset(&motif_top_level_leave_postponed_event, 0,
- sizeof(XClientMessageEvent));
- }
-
- /*
- * This code forwards drag notifications to the browser according to the
- * following rules:
- * - the messages that we failed to process are always forwarded to the
- * browser;
- * - MotionEvents and DropEvents are forwarded if and only if the drag
- * is not over a plugin window;
- * - XDnD: EnterEvents and LeaveEvents are never forwarded, instead, we
- * send synthesized EnterEvents or LeaveEvents when the drag
- * respectively exits or enters plugin windows;
- * - Motif DnD: EnterEvents and LeaveEvents are always forwarded.
- * Synthetic EnterEvents and LeaveEvents are needed, because the XDnD drop
- * site implemented Netscape 6.2 has a nice feature: when it receives
- * the first XdndPosition it continuously sends XdndStatus messages to
- * the source (every 100ms) until the drag terminates or leaves the drop
- * site. When the mouse is dragged over plugin window embedded in the
- * browser frame, these XdndStatus messages are mixed with the XdndStatus
- * messages sent from the plugin.
- * For Motif DnD, synthetic events cause Motif warnings being displayed,
- * so these events are always forwarded. However, Motif DnD drop site in
- * Netscape 6.2 is implemented in the same way, so there could be similar
- * problems if the drag source choose Motif DnD for communication.
- */
- switch (status) {
- case EventFailure:
- forward_client_message_to_toplevel(win, xclient);
- break;
- case EventSuccess:
- {
- /* True iff the previous notification was MotionEvent and it was
- forwarded to the browser. */
- static Boolean motion_passed_along = False;
-
- Boolean motif_protocol =
- xclient->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
-
- switch (type) {
- case MotionEvent:
- if (JNU_IsNull(env, target_component)) {
- if (!motion_passed_along && !motif_protocol) {
- send_enter_message_to_toplevel(win, xclient);
- }
- forward_client_message_to_toplevel(win, xclient);
- motion_passed_along = True;
- } else {
- if (motion_passed_along && !motif_protocol) {
- send_leave_message_to_toplevel(win, xclient);
- }
- motion_passed_along = False;
- }
- break;
- case DropEvent:
- if (JNU_IsNull(env, target_component)) {
- forward_client_message_to_toplevel(win, xclient);
- /* The last chance to cleanup. */
- awt_dnd_cleanup();
- }
- motion_passed_along = False;
- break;
- case EnterEvent:
- case LeaveEvent:
- if (motif_protocol) {
- forward_client_message_to_toplevel(win, xclient);
- }
- motion_passed_along = False;
- break;
- }
- }
- }
-
- if (postponed_leave) {
- XUngrabServer(awt_display);
- }
- }
-}
-
-/*
- * Returns True if the event is processed and shouldn't be passed along to Java.
- * Otherwise, return False.
- */
-Boolean
-awt_dnd_dt_process_event(XEvent* event) {
- Display* dpy = event->xany.display;
- EventStatus status = EventFailure;
- EventType type = UnknownEvent;
-
- if (event->type == DestroyNotify) {
- if (event->xany.window == source_window) {
- awt_dnd_cleanup();
- }
- /* pass along */
- return False;
- }
-
- if (event->type == PropertyNotify) {
- if (is_embedding_toplevel(event->xany.window)) {
- Atom atom = event->xproperty.atom;
- /*
- * If some other client replaced the XDnD or Motif DnD proxy with
- * another window we set the proxy back to the awt_root_window
- * and update the entry in the embedded_drop_site_list.
- * This code is needed, as for example Netscape 4.7 resets the proxy
- * when the browser shell is resized.
- */
- if (atom == _XA_MOTIF_DRAG_RECEIVER_INFO) {
- Window prev_motif_proxy;
- ProxyRegistrationStatus status;
- status = set_motif_proxy(event->xany.display, event->xany.window,
- get_awt_root_window(), &prev_motif_proxy);
- if (status != RegFailure && status != RegAlreadyRegistered) {
- set_motif_proxy_for_toplevel(event->xany.window,
- prev_motif_proxy,
- status == RegOverride);
- }
- }
-
- if (atom == XA_XdndAware || atom == XA_XdndProxy) {
- Window prev_xdnd_proxy;
- unsigned int prev_protocol_version;
- ProxyRegistrationStatus status;
- status = set_xdnd_proxy(event->xany.display, event->xany.window,
- get_awt_root_window(), &prev_xdnd_proxy,
- &prev_protocol_version);
- if (status != RegFailure && status != RegAlreadyRegistered) {
- set_xdnd_proxy_for_toplevel(event->xany.window,
- prev_xdnd_proxy,
- prev_protocol_version,
- status == RegOverride);
- }
- }
- }
- /* pass along */
- return False;
- }
-
- if (event->type != ClientMessage) {
- return False;
- }
-
- if (get_component_for_window(event->xany.window) == NULL &&
- !is_embedding_toplevel(event->xany.window)) {
- return False;
- }
-
- if (motif_top_level_leave_postponed) {
- /* Sanity check. */
- if (source_protocol != MOTIF_DND_PROTOCOL) {
- DTRACE_PRINTLN2("%s:%d TOP_LEVEL_LEAVE rejected - invalid state.",
- __FILE__, __LINE__);
- awt_dnd_cleanup();
- } else if (event->xclient.message_type ==
- _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
- unsigned char first_byte = event->xclient.data.b[0];
- unsigned char reason = first_byte & MOTIF_MESSAGE_REASON_MASK;
- unsigned char origin = first_byte & MOTIF_MESSAGE_SENDER_MASK;
-
- if (origin == MOTIF_MESSAGE_FROM_INITIATOR &&
- reason != DROP_START) {
- awt_dnd_cleanup();
- }
- } else {
- awt_dnd_cleanup();
- }
- }
-
- if (event->xclient.message_type == XA_XdndEnter) {
- status = handle_xdnd_enter(&event->xclient);
- type = EnterEvent;
- } else if (event->xclient.message_type == XA_XdndPosition) {
- status = handle_xdnd_position(&event->xclient);
- type = MotionEvent;
- } else if (event->xclient.message_type == XA_XdndLeave) {
- status = handle_xdnd_leave(&event->xclient);
- type = LeaveEvent;
- } else if (event->xclient.message_type == XA_XdndDrop) {
- status = handle_xdnd_drop(&event->xclient);
- type = DropEvent;
- } else if (event->xclient.message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
- unsigned char reason = event->xclient.data.b[0] & MOTIF_MESSAGE_REASON_MASK;
- unsigned char origin = event->xclient.data.b[0] & MOTIF_MESSAGE_SENDER_MASK;
-
- /* Only initiator messages should be handled. */
- if (origin == MOTIF_MESSAGE_FROM_INITIATOR) {
- switch (reason) {
- case DRAG_MOTION:
- case OPERATION_CHANGED:
- status = handle_motif_drag_motion(&event->xclient);
- type = MotionEvent;
- break;
- case TOP_LEVEL_ENTER:
- status = handle_motif_top_level_enter(&event->xclient);
- type = EnterEvent;
- break;
- case TOP_LEVEL_LEAVE:
- status = handle_motif_top_level_leave(&event->xclient);
- type = LeaveEvent;
- break;
- case DROP_START:
- status = handle_motif_drop_start(&event->xclient);
- type = DropEvent;
- break;
- }
- }
- } else {
- /* Unknown message type. */
- return False;
- }
-
- /*
- * We need to handle a special case here: Motif DnD protocol prescribed that
- * DROP_START message should always be preceeded with TOP_LEVEL_LEAVE
- * message. We need to cleanup on TOP_LEVEL_LEAVE message, but DROP_START
- * wouldn't be processed properly. Instead we postpone the cleanup and
- * send a dummy client message to ourselves. If dummy arrives first we do a
- * normal cleanup. If DROP_START arrives before the dummy we discard delayed
- * cleanup.
- * In case of forwarding events from an embedded Java app to an embedding
- * Java app it could happen that the embedding app receives the dummy before
- * the DROP_START message arrives from the embedding app. In this case the
- * drop operation on the embedding app fails to complete.
- * To resolve this problem we postpone forwarding of TOP_LEVEL_LEAVE message
- * until the next client message is about to be forwarded.
- */
- if (motif_top_level_leave_postponed && type == LeaveEvent) {
- /* motif_top_level_leave_postponed can be set only if the latest client
- message has been processed successfully. */
- DASSERT(status == EventSuccess);
- memcpy(&motif_top_level_leave_postponed_event, &event->xclient,
- sizeof(XClientMessageEvent));
- } else {
- post_process_client_message(&event->xclient, status, type);
- }
-
- return True;
-}
-
-static Boolean
-register_xdnd_drop_site(Display* dpy, Window toplevel, Window window) {
- unsigned char ret;
- Atom version_atom = XDND_PROTOCOL_VERSION;
-
- ret = checked_XChangeProperty(dpy, window, XA_XdndAware, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char*)&version_atom, 1);
-
- return (ret == Success);
-}
-
-static Boolean
-register_motif_drop_site(Display* dpy, Window toplevel, Window window) {
- unsigned char status;
- size_t data_size = MOTIF_RECEIVER_INFO_SIZE;
- char* data = malloc(data_size);
- void* p = data;
-
- if (data == NULL) {
- DTRACE_PRINTLN2("%s:%d malloc failed.", __FILE__, __LINE__);
- return False;
- }
-
- write_card8(&p, MOTIF_BYTE_ORDER);
- write_card8(&p, MOTIF_DND_PROTOCOL_VERSION); /* protocol version */
- write_card8(&p, MOTIF_DYNAMIC_STYLE); /* protocol style */
- write_card8(&p, 0); /* pad */
- write_card32(&p, window); /* proxy window */
- write_card16(&p, 0); /* num_drop_sites */
- write_card16(&p, 0); /* pad */
- write_card32(&p, data_size);
-
- status = checked_XChangeProperty(dpy, window, _XA_MOTIF_DRAG_RECEIVER_INFO,
- _XA_MOTIF_DRAG_RECEIVER_INFO, 8, PropModeReplace,
- (unsigned char*)data, data_size);
-
- free(data);
-
- return (status == Success);
-}
-
-static Window
-find_toplevel_window(Display* dpy, Window window) {
- Window ret = None;
- Window root = None;
- Window parent = None;
- Window *children;
- unsigned int nchildren;
-
- int status;
-
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char *data;
-
- /* Traverse the ancestor tree from window up to the root and find
- the top-level client window nearest to the root. */
- do {
- type = None;
-
- data = NULL;
- status = XGetWindowProperty(dpy, window, XA_WM_STATE, 0, 0, False,
- AnyPropertyType, &type, &format, &nitems,
- &after, &data);
-
- if (status == Success) {
- XFree(data);
- }
-
- if (type != None) {
- ret = window;
- }
-
- if (!XQueryTree(dpy, window, &root, &parent, &children, &nchildren)) {
- return None;
- }
-
- XFree(children);
-
- window = parent;
- } while (window != root);
-
- return ret;
-}
-
-static Boolean
-register_drop_site(Widget outer_canvas, XtPointer componentRef) {
- Display* dpy = XtDisplay(outer_canvas);
- Widget shell = NULL;
- /* Shell window. */
- Window window = None;
- Window root = None;
- Window toplevel = None;
-
- for (shell = outer_canvas; shell != NULL && !XtIsShell(shell);
- shell = XtParent(shell));
-
- if (shell == NULL || !XtIsRealized(shell)) {
- DTRACE_PRINTLN2("%s:%d Cannot find a realized shell for the widget.",
- __FILE__, __LINE__);
- return False;
- }
-
- window = XtWindow(shell);
-
- if (!awt_dnd_init(dpy)) {
- DTRACE_PRINTLN2("%s:%d Fail to initialize.", __FILE__, __LINE__);
- return False;
- }
-
- {
- XWindowAttributes xwa;
-
- if (!XGetWindowAttributes(dpy, window, &xwa)) {
- DTRACE_PRINTLN2("%s:%d XGetWindowAttributes failed.", __FILE__, __LINE__);
- return False;
- }
-
- root = xwa.root;
-
- if (root == None) {
- DTRACE_PRINTLN2("%s:%d Bad root.", __FILE__, __LINE__);
- return False;
- }
- }
-
- toplevel = find_toplevel_window(dpy, window);
-
- /*
- * No window with WM_STATE property is found.
- * Since the window can be a plugin window reparented to the browser
- * toplevel, we cannot determine which window will eventually have WM_STATE
- * property set. So we schedule a timer callback that will periodically
- * attempt to find an ancestor with WM_STATE and register the drop site
- * appropriately.
- */
- if (toplevel == None) {
- add_delayed_registration_entry(outer_canvas, componentRef);
- return False;
- }
-
- if (toplevel == window) {
- Boolean xdnd_registered = False;
- Boolean motif_registered = False;
-
- xdnd_registered = register_xdnd_drop_site(dpy, toplevel, window);
-
- motif_registered = register_motif_drop_site(dpy, toplevel, window);
-
- if (!xdnd_registered && !motif_registered) {
- DTRACE_PRINTLN2("%s:%d Failed to register.", __FILE__, __LINE__);
- return False;
- }
- } else {
- if (!add_to_embedded_drop_site_list(dpy, root, toplevel, window)) {
- DTRACE_PRINTLN2("%s:%d Failed to init proxy.", __FILE__, __LINE__);
- return False;
- }
- }
-
- /* There is no need to update the window for the component later, since the
- window is destroyed only when the component is disposed in which case the
- drop site will be unregistered as well. */
- if (add_to_drop_site_list(window, root, toplevel, XtWindow(outer_canvas),
- (jobject)componentRef)) {
- DTRACE_PRINTLN2("%s:%d Drop site registered.", __FILE__, __LINE__);
- return True;
- } else {
- DTRACE_PRINTLN2("%s:%d Failed to register.", __FILE__, __LINE__);
- return False;
- }
-}
-
-static void
-register_drop_site_when_realized(Widget outer_canvas, XtPointer client_data,
- XEvent *event, Boolean *dontSwallow) {
- if (XtIsRealized(outer_canvas)) {
- XtRemoveEventHandler(outer_canvas, StructureNotifyMask, False,
- register_drop_site_when_realized, client_data);
-
- register_drop_site(outer_canvas, client_data);
- }
-}
-
-/*
- * Registers the top-level Window that contains the specified widget as a drop
- * site that supports XDnD and Motif DnD protocols.
- * If the registration fails for some reason, adds an event handler that will
- * attempt to register the drop site later.
- *
- * Returns True if the drop site is registered successfully.
- */
-static Boolean
-awt_dnd_register_drop_site(Widget outer_canvas, XtPointer componentRef) {
- if (XtIsRealized(outer_canvas)) {
- return register_drop_site(outer_canvas, componentRef);
- } else {
- XtAddEventHandler(outer_canvas, StructureNotifyMask, False,
- register_drop_site_when_realized,
- componentRef);
-
- DTRACE_PRINTLN2("%s:%d Unrealized shell. Register later.",
- __FILE__, __LINE__);
-
- return True;
- }
-}
-
-/*
- * Unregisters the drop site associated with the top-level Window that contains
- * the specified widget .
- *
- * Returns True if completes successfully, False otherwise.
- */
-static Boolean
-awt_dnd_unregister_drop_site(Widget outer_canvas, XtPointer componentRef) {
- Widget shell = NULL;
-
- XtRemoveEventHandler(outer_canvas, StructureNotifyMask, False,
- register_drop_site_when_realized, componentRef);
-
- remove_delayed_registration_entry(outer_canvas);
-
- for (shell = outer_canvas; shell != NULL && !XtIsShell(shell);
- shell = XtParent(shell));
-
- if (shell != NULL && XtIsShell(shell) && XtIsRealized(shell)) {
- Window win = XtWindow(shell);
- Window toplevel = get_toplevel_for_window(win);
- /*
- * Cleanup the global state if this drop site participate in the current
- * drag operation. Particularly, this allows to delete global ref to the
- * component safely.
- */
- if (get_component_for_window(win) == target_component) {
- awt_dnd_cleanup();
- }
- if (toplevel != win) {
- remove_from_embedded_drop_site_list(awt_display, toplevel, win);
- }
- return remove_from_drop_site_list(win);
- }
-
- return True;
-}
-
-/**************************** XEmbed server DnD support ***********************/
-
-/*
- *
- *
- */
-Boolean
-register_xembed_drop_site(JNIEnv* env, Display* dpy, jobject server,
- Window serverHandle, Window clientHandle) {
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char* data;
- unsigned char ret;
- unsigned int protocol_version;
-
- Window xdnd_proxy = None;
- unsigned int xdnd_protocol_version = 0;
- Boolean xdnd_override = False;
-
- if (!awt_dnd_init(dpy)) {
- DTRACE_PRINTLN2("%s:%d Fail to initialize.", __FILE__, __LINE__);
- return False;
- }
-
- /* Get the XDnD protocol version and XDnD proxy of the XEmbed client. */
- data = NULL;
- ret = checked_XGetWindowProperty(dpy, clientHandle, XA_XdndAware, 0, 1,
- False, AnyPropertyType, &type, &format,
- &nitems, &after, &data);
-
- /* XEmbed client doesn't have an associated XDnD drop site -
- do nothing and return True to indicate success. */
- if (ret != Success || data == NULL || nitems == 0 || type != XA_ATOM) {
- XFree(data);
- return False;
- }
-
- protocol_version = *((unsigned int*)data);
-
- XFree(data);
-
- if (protocol_version < XDND_MIN_PROTOCOL_VERSION) {
- return False;
- }
-
- xdnd_protocol_version = protocol_version;
-
- /* XdndProxy is not supported prior to XDnD version 4 */
- if (protocol_version >= 4) {
- int status;
-
- data = NULL;
- status = XGetWindowProperty(dpy, clientHandle, XA_XdndProxy, 0, 1,
- False, XA_WINDOW, &type, &format,
- &nitems, &after, &data);
-
- if (status == Success && data != NULL && type == XA_WINDOW) {
- xdnd_proxy = *((Window*)data);
-
- if (xdnd_proxy != None) {
- XFree(data);
-
- data = NULL;
- status = XGetWindowProperty(dpy, xdnd_proxy, XA_XdndProxy,
- 0, 1, False, XA_WINDOW, &type,
- &format, &nitems, &after,
- &data);
-
- if (status != Success || data == NULL || type != XA_WINDOW ||
- *((Window*)data) != xdnd_proxy) {
- /* Ignore invalid proxy. */
- xdnd_proxy = None;
- }
- }
-
- if (xdnd_proxy != None) {
- XFree(data);
-
- data = NULL;
- status = XGetWindowProperty(dpy, xdnd_proxy, XA_XdndAware, 0, 1,
- False, AnyPropertyType, &type,
- &format, &nitems, &after, &data);
-
- if (status == Success && data != NULL && type == XA_ATOM) {
- unsigned int proxy_version = *((unsigned int*)data);
-
- if (proxy_version != protocol_version) {
- /* Ignore invalid proxy. */
- xdnd_proxy = None;
- }
- } else {
- /* Ignore invalid proxy. */
- xdnd_proxy = None;
- }
- }
- }
-
- XFree(data);
- }
-
- set_xembed_drop_target(env, server);
-
- /* Add protocol specific entries for the embedded window. */
- /* Only XDnD protocol is supported for XEmbed clients. */
- {
- EmbeddedDropSiteProtocolListEntry* xdnd_entry = NULL;
-
- xdnd_entry = malloc(sizeof(EmbeddedDropSiteProtocolListEntry));
-
- if (xdnd_entry == NULL) {
- return False;
- }
-
- xdnd_entry->window = clientHandle;
- xdnd_entry->proxy = xdnd_proxy;
- xdnd_entry->protocol_version = xdnd_protocol_version;
- xdnd_entry->overriden = True;
- xdnd_entry->next = embedded_xdnd_protocol_list;
- embedded_xdnd_protocol_list = xdnd_entry;
- }
-
- {
- EmbeddedDropSiteListEntry* entry = NULL;
- Window* sites = NULL;
-
- entry = malloc(sizeof(EmbeddedDropSiteListEntry));
-
- if (entry == NULL) {
- return False;
- }
-
- sites = malloc(sizeof(Window));
-
- if (sites == NULL) {
- free(entry);
- return False;
- }
-
- sites[0] = clientHandle;
-
- entry->toplevel = serverHandle;
- entry->root = None;
- entry->event_mask = 0;
- entry->embedded_sites_count = 1;
- entry->embedded_sites = sites;
- entry->next = embedded_drop_site_list;
- embedded_drop_site_list = entry;
- }
-
- return True;
-}
-
-Boolean
-unregister_xembed_drop_site(JNIEnv* env, Display* dpy, jobject server,
- Window serverHandle, Window clientHandle) {
- remove_from_embedded_drop_site_list(dpy, serverHandle, clientHandle);
- return True;
-}
-
-void
-forward_event_to_embedded(Window embedded, jlong ctxt, jint eventID) {
- static XClientMessageEvent* prevMessage = NULL;
- static Boolean overXEmbedClient = False;
-
- XClientMessageEvent* xclient =
- (XClientMessageEvent*)jlong_to_ptr(ctxt);
-
- if (xclient == NULL && prevMessage == NULL) {
- return;
- }
-
- if (xclient != NULL) {
- /*
- * NOTE: this check guarantees that prevMessage will always be an XDnD
- * drag message.
- */
- if (!is_xdnd_drag_message_type(xclient->message_type)) {
- return;
- }
-
- if (!overXEmbedClient) {
- long* appended_data = jlong_to_ptr(ctxt) +
- sizeof(XClientMessageEvent);
-
- /* Copy XdndTypeList from source to proxy. */
- if ((appended_data[0] & XDND_DATA_TYPES_BIT) != 0) {
- unsigned char ret;
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char *data;
-
- data = NULL;
- ret = checked_XGetWindowProperty(xclient->display,
- xclient->data.l[0],
- XA_XdndTypeList, 0, 0xFFFF,
- False, XA_ATOM, &type, &format,
- &nitems, &after, &data);
-
- /* Ignore the source if the window is destroyed. */
- if (ret == BadWindow) {
- return;
- }
-
- if (ret == Success) {
- if (type == XA_ATOM && format == 32) {
- ret = checked_XChangeProperty(xclient->display,
- xclient->window,
- XA_XdndTypeList, XA_ATOM,
- 32, PropModeReplace, data,
- nitems);
- }
-
- XFree(data);
- }
- }
-
- set_proxy_mode_source_window(xclient->data.l[0]);
-
- {
- XClientMessageEvent enter;
- enter.display = xclient->display;
- enter.type = ClientMessage;
- enter.window = embedded;
- enter.format = 32;
- enter.message_type = XA_XdndEnter;
-
- enter.data.l[0] = xclient->window; /* XID of the source window */
- enter.data.l[1] = appended_data[0];
- enter.data.l[2] = appended_data[1];
- enter.data.l[3] = appended_data[2];
- enter.data.l[4] = appended_data[3];
-
- forward_client_message_to_toplevel(embedded, &enter);
- }
-
- overXEmbedClient = True;
- }
-
- /* Make a copy of the original event, since we are going to modify the
- event while it still can be referenced from other Java events. */
- {
- XClientMessageEvent copy;
- memcpy(©, xclient, sizeof(XClientMessageEvent));
- copy.data.l[0] = xclient->window;
-
- forward_client_message_to_toplevel(embedded, ©);
- }
- }
-
- if (eventID == java_awt_event_MouseEvent_MOUSE_EXITED) {
- if (overXEmbedClient) {
- if (xclient != NULL || prevMessage != NULL) {
- /* Last chance to send XdndLeave to the XEmbed client. */
- XClientMessageEvent leave;
-
- leave.display = xclient != NULL ?
- xclient->display : prevMessage->display;
- leave.type = ClientMessage;
- leave.window = embedded;
- leave.format = 32;
- leave.message_type = XA_XdndLeave;
- leave.data.l[0] = xclient != NULL ?
- xclient->window : prevMessage->window; /* XID of the source window */
- leave.data.l[1] = 0; /* flags */
-
- forward_client_message_to_toplevel(embedded, &leave);
- }
- overXEmbedClient = False;
- }
- }
-
- if (eventID == java_awt_event_MouseEvent_MOUSE_RELEASED) {
- overXEmbedClient = False;
- awt_dnd_cleanup();
- }
-
- if (prevMessage != 0) {
- free(prevMessage);
- prevMessage = 0;
- }
-
- if (xclient != 0 && overXEmbedClient) {
- prevMessage = malloc(sizeof(XClientMessageEvent));
-
- memcpy(prevMessage, xclient, sizeof(XClientMessageEvent));
- }
-}
-
-/******************************************************************************/
-
-/*
- * Class: sun_awt_motif_MWindowPeer
- * Method: registerX11DropTarget
- * Signature: (Ljava/awt/Component;)V
- */
-
-JNIEXPORT void JNICALL
-Java_sun_awt_motif_MWindowPeer_registerX11DropTarget(JNIEnv *env, jobject this,
- jobject target) {
- struct FrameData* wdata = NULL;
- DropSitePtr dsi = NULL;
-
- wdata = (struct FrameData *)
- JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
-
- if (wdata == NULL || wdata->winData.comp.widget == NULL) {
- JNU_ThrowNullPointerException(env, "NULL component data");
- return;
- }
-
- if (wdata->winData.shell == NULL) {
- JNU_ThrowNullPointerException(env, "Null shell widget");
- return;
- }
-
- DASSERT(wdata->winData.comp.dsi == NULL);
-
- dsi = (DropSitePtr)calloc(1, sizeof(struct DropSiteInfo));
-
- if (dsi == NULL) {
- JNU_ThrowOutOfMemoryError(env, "");
- return;
- }
-
- dsi->component = (*env)->NewGlobalRef(env, target);
- dsi->isComposite = False;
-
- wdata->winData.comp.dsi = dsi;
-
- AWT_LOCK();
-
- awt_dnd_register_drop_site(wdata->winData.comp.widget,
- dsi->component);
-
- AWT_UNLOCK();
-}
-
-/*
- * Class: sun_awt_motif_MWindowPeer
- * Method: unregisterX11DropTarget
- * Signature: (Ljava/awt/Component;)V
- */
-
-JNIEXPORT void JNICALL
-Java_sun_awt_motif_MWindowPeer_unregisterX11DropTarget(JNIEnv *env,
- jobject this,
- jobject target) {
- struct FrameData* wdata = NULL;
- DropSitePtr dsi = NULL;
-
- wdata = (struct FrameData *)
- JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
-
- if (wdata == NULL) {
- JNU_ThrowNullPointerException(env, "Null component data");
- return;
- }
-
- if (wdata->winData.shell == NULL) {
- JNU_ThrowNullPointerException(env, "Null shell widget");
- return;
- }
-
- dsi = wdata->winData.comp.dsi;
-
- if (dsi == NULL) {
- JNU_ThrowNullPointerException(env, "Null DropSiteInfo");
- return;
- }
-
- AWT_LOCK();
-
- awt_dnd_unregister_drop_site(wdata->winData.comp.widget, dsi->component);
-
- AWT_UNLOCK();
-
- wdata->winData.comp.dsi = NULL;
-
- (*env)->DeleteGlobalRef(env, dsi->component);
-
- free(dsi);
-}
-
-static void
-dt_send_event_to_source(XClientMessageEvent* xclient) {
- /* Shortcut if the source is in the same JVM. */
- if (xclient->window == awt_dnd_ds_get_source_window()) {
- awt_dnd_ds_process_event((XEvent*)xclient);
- } else {
- unsigned char ret;
-
- ret = checked_XSendEvent(xclient->display, xclient->window, False,
- NoEventMask, (XEvent*)xclient);
-
- if (ret == BadWindow) {
- DTRACE_PRINTLN2("%s:%d XSendEvent - invalid window.",
- __FILE__, __LINE__);
-
- /* Cleanup if we are still communicating with this window. */
- if (source_window == xclient->window) {
- awt_dnd_cleanup();
- }
- }
- }
-}
-
-static void
-dt_send_response(XClientMessageEvent* xclient, jint eventID, jint action) {
- Display* dpy = xclient->display;
- XClientMessageEvent response;
-
- if (xclient->message_type == XA_XdndPosition) {
- long* event_data = xclient->data.l;
-
- if (eventID == java_awt_event_MouseEvent_MOUSE_EXITED) {
- action = java_awt_dnd_DnDConstants_ACTION_NONE;
- }
-
- response.display = dpy;
- response.type = ClientMessage;
- response.window = event_data[0];
- response.format = 32;
- response.message_type = XA_XdndStatus;
- /* target window */
- response.data.l[0] = xclient->window;
- /* flags */
- response.data.l[1] = 0;
- if (action != java_awt_dnd_DnDConstants_ACTION_NONE) {
- response.data.l[1] |= XDND_ACCEPT_DROP_FLAG;
- }
- /* specify an empty rectangle */
- response.data.l[2] = 0; /* x, y */
- response.data.l[3] = 0; /* w, h */
- /* action accepted by the target */
- response.data.l[4] = java_to_xdnd_action(action);
- } else if (xclient->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
- int reason = (int)(xclient->data.b[0] & MOTIF_MESSAGE_REASON_MASK);
- int origin = (int)(xclient->data.b[0] & MOTIF_MESSAGE_SENDER_MASK);
- unsigned char byte_order = xclient->data.b[1];
- CARD16 response_flags = 0;
- CARD8 response_reason = 0;
- void* p = &response.data.b;
-
- /* Only initiator messages should be handled. */
- if (origin != MOTIF_MESSAGE_FROM_INITIATOR) {
- DTRACE_PRINTLN2("%s:%d Receiver message.", __FILE__, __LINE__);
- return;
- }
-
- switch (reason) {
- case DRAG_MOTION:
- switch (eventID) {
- case java_awt_event_MouseEvent_MOUSE_ENTERED:
- response_reason = DROP_SITE_ENTER;
- break;
- case java_awt_event_MouseEvent_MOUSE_DRAGGED:
- response_reason = DRAG_MOTION;
- break;
- case java_awt_event_MouseEvent_MOUSE_EXITED:
- response_reason = DROP_SITE_LEAVE;
- break;
- }
- }
-
- response.display = dpy;
- response.type = ClientMessage;
- response.window = read_card32(xclient->data.b, 12, byte_order);
- response.format = 8;
- response.message_type = _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
-
- write_card8(&p, response_reason | MOTIF_MESSAGE_FROM_RECEIVER);
- write_card8(&p, MOTIF_BYTE_ORDER);
-
- if (response_reason != DROP_SITE_LEAVE) {
- CARD16 flags = read_card16(xclient->data.b, 2, byte_order);
- unsigned char drop_site_status =
- (action == java_awt_dnd_DnDConstants_ACTION_NONE) ?
- MOTIF_INVALID_DROP_SITE : MOTIF_VALID_DROP_SITE;
-
- /* Clear action and drop site status bits. */
- response_flags =
- flags & ~MOTIF_DND_ACTION_MASK & ~MOTIF_DND_STATUS_MASK;
-
- /* Fill in new action and drop site status. */
- response_flags |=
- java_to_motif_actions(action) << MOTIF_DND_ACTION_SHIFT;
- response_flags |=
- drop_site_status << MOTIF_DND_STATUS_SHIFT;
- } else {
- response_flags = 0;
- }
-
- write_card16(&p, response_flags);
-
- /* Write time stamp. */
- write_card32(&p, read_card32(xclient->data.b, 4, byte_order));
-
- /* Write coordinates. */
- if (response_reason != DROP_SITE_LEAVE) {
- write_card16(&p, read_card16(xclient->data.b, 8, byte_order));
- write_card16(&p, read_card16(xclient->data.b, 10, byte_order));
- } else {
- write_card16(&p, 0);
- write_card16(&p, 0);
- }
- } else {
- return;
- }
-
- dt_send_event_to_source(&response);
-}
-
-static void
-dummy_selection_callback(Widget w, XtPointer client_data, Atom* selection,
- Atom* type, XtPointer value, unsigned long *length,
- int32_t *format) {
- /* The selection callback is responsible for freeing the data. */
- if (value != NULL) {
- XtFree(value);
- value = NULL;
- }
-}
-
-static void
-dt_notify_drop_done(JNIEnv* env, XClientMessageEvent* xclient, jboolean success,
- jint action) {
- if (xclient->message_type == XA_XdndDrop) {
- Display* dpy = xclient->display;
- XClientMessageEvent finished;
- long* event_data = xclient->data.l;
-
- /*
- * The XDnD protocol recommends that the target requests the special
- * target DELETE in case if the drop action is XdndActionMove.
- */
- if (action == java_awt_dnd_DnDConstants_ACTION_MOVE &&
- success == JNI_TRUE) {
-
- Time time_stamp = event_data[2];
-
- XtGetSelectionValue(awt_root_shell, XA_XdndSelection, XA_DELETE,
- dummy_selection_callback, NULL, time_stamp);
- }
-
- finished.display = dpy;
- finished.type = ClientMessage;
- finished.window = event_data[0];
- finished.format = 32;
- finished.message_type = XA_XdndFinished;
- finished.data.l[0] = xclient->window;
- finished.data.l[1] = 0; /* flags */
- finished.data.l[2] = None;
- if (source_protocol_version >= 5) {
- if (success == JNI_TRUE) {
- finished.data.l[1] |= XDND_ACCEPT_DROP_FLAG;
- }
- finished.data.l[2] = java_to_xdnd_action(action);
- }
-
- dt_send_event_to_source(&finished);
- } else if (xclient->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
- char* event_data = xclient->data.b;
- unsigned char event_byte_order = read_card8(event_data, 1);
- unsigned char first_byte = read_card8(event_data, 0);
- unsigned char reason = first_byte & MOTIF_MESSAGE_REASON_MASK;
- unsigned char origin = first_byte & MOTIF_MESSAGE_SENDER_MASK;
- Atom selection = None;
- Time time_stamp = CurrentTime;
- Atom status_atom = None;
-
- if (origin != MOTIF_MESSAGE_FROM_INITIATOR) {
- DTRACE_PRINTLN2("%s:%d Invalid origin.", __FILE__, __LINE__);
- return;
- }
-
- if (reason != DROP_START) {
- DTRACE_PRINTLN2("%s:%d Invalid reason.", __FILE__, __LINE__);
- return;
- }
-
- selection = read_card32(event_data, 12, event_byte_order);
- time_stamp = read_card32(event_data, 4, event_byte_order);
-
- if (success == JNI_TRUE) {
- status_atom = XA_XmTRANSFER_SUCCESS;
- } else {
- status_atom = XA_XmTRANSFER_FAILURE;
- }
-
- /*
- * This is just the way to communicate the drop completion status back
- * to the initiator as prescribed by the Motif DnD protocol.
- */
- XtGetSelectionValue(awt_root_shell, selection, status_atom,
- dummy_selection_callback, NULL, time_stamp);
- }
-
- /*
- * Flush the buffer to guarantee that the drop completion event is sent
- * to the source before the method returns.
- */
- XFlush(awt_display);
-
- /* Trick to prevent awt_dnd_cleanup() from posting dragExit */
- target_component = NULL;
- /* Cannot do cleanup before the drop finishes as we need source protocol
- version to send XdndFinished message. */
- awt_dnd_cleanup();
-}
-
-/*
- * Class: sun_awt_motif_X11DropTargetContextPeer
- * Method: sendResponse
- * Signature: (IIJZ)V
- */
-
-JNIEXPORT void JNICALL
-Java_sun_awt_motif_X11DropTargetContextPeer_sendResponse(JNIEnv *env,
- jobject this,
- jint eventID,
- jint action,
- jlong nativeCtxt,
- jboolean dispatcherDone,
- jboolean consumed) {
- XClientMessageEvent* xclient =
- (XClientMessageEvent*)jlong_to_ptr(nativeCtxt);
-
- AWT_LOCK();
-
- if (consumed == JNI_FALSE) {
- dt_send_response(xclient, eventID, action);
- }
-
- /*
- * Free the native context only if all copies of the original event are
- * processed.
- */
- if (dispatcherDone == JNI_TRUE) {
- XtFree((char*)xclient);
- }
-
- AWT_UNLOCK();
-}
-
-/*
- * Class: sun_awt_motif_X11DropTargetContextPeer
- * Method: dropDone
- * Signature: (JZI)V
- */
-
-JNIEXPORT void JNICALL
-Java_sun_awt_motif_X11DropTargetContextPeer_dropDone(JNIEnv *env,
- jobject this,
- jlong nativeCtxt,
- jboolean success,
- jint action) {
- XClientMessageEvent* xclient =
- (XClientMessageEvent*)jlong_to_ptr(nativeCtxt);
-
- AWT_LOCK();
-
- dt_notify_drop_done(env, xclient, success, action);
-
- XtFree((char*)xclient);
-
- AWT_UNLOCK();
-}
-
-/*
- * Class: sun_awt_motif_X11DropTargetContextPeer
- * Method: getData
- * Signature: (IJ)Ljava/lang/Object;
- */
-
-JNIEXPORT jobject JNICALL
-Java_sun_awt_motif_X11DropTargetContextPeer_getData(JNIEnv *env,
- jobject this,
- jlong nativeCtxt,
- jlong formatAtom) {
- XClientMessageEvent* xclient =
- (XClientMessageEvent*)jlong_to_ptr(nativeCtxt);
-
- Atom selection = None;
- Time time_stamp = CurrentTime;
- Atom target = (Atom)formatAtom;
-
- if (xclient->message_type == XA_XdndDrop ||
- xclient->message_type == XA_XdndPosition) {
- Display* dpy = xclient->display;
- Window source_win = xclient->data.l[0];
- Atom protocol_version = 0;
-
- int status;
-
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long after;
- unsigned char *data;
-
- AWT_LOCK();
-
- data = NULL;
- status = XGetWindowProperty(dpy, source_win, XA_XdndAware, 0, 0xFFFF,
- False, XA_ATOM, &type, &format, &nitems,
- &after, &data);
-
- if (status == Success && data != NULL && type == XA_ATOM && format == 32
- && nitems > 0) {
- protocol_version = (protocol_version > XDND_PROTOCOL_VERSION) ?
- XDND_PROTOCOL_VERSION : protocol_version;
-
- if (protocol_version > 0) {
- if (xclient->message_type == XA_XdndDrop) {
- time_stamp = xclient->data.l[2];
- } else if (xclient->message_type == XA_XdndPosition) {
- time_stamp = xclient->data.l[3];
- }
- }
- }
-
- if (status == Success) {
- XFree(data);
- data = NULL;
- }
-
- AWT_FLUSH_UNLOCK();
-
- selection = XA_XdndSelection;
- if (time_stamp == CurrentTime) {
- time_stamp = awt_util_getCurrentServerTime();
- }
-
- } else if (xclient->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
- char* event_data = xclient->data.b;
- unsigned char event_byte_order = read_card8(event_data, 1);
- unsigned char first_byte = read_card8(event_data, 0);
- unsigned char reason = first_byte & MOTIF_MESSAGE_REASON_MASK;
- unsigned char origin = first_byte & MOTIF_MESSAGE_SENDER_MASK;
-
- if (origin != MOTIF_MESSAGE_FROM_INITIATOR) {
- DTRACE_PRINTLN2("%s:%d Invalid origin.", __FILE__, __LINE__);
- return NULL;
- }
-
- switch (reason) {
- case DROP_START:
- selection = read_card32(event_data, 12, event_byte_order);
- break;
- case DRAG_MOTION:
- case OPERATION_CHANGED:
- selection = source_atom;
- break;
- default:
- DTRACE_PRINTLN2("%s:%d Invalid reason.", __FILE__, __LINE__);
- return NULL;
- }
-
- if (selection == None) {
- return NULL;
- }
-
- time_stamp = read_card32(event_data, 4, event_byte_order);
- } else {
- return NULL;
- }
-
- return get_selection_data(env, selection, target, time_stamp);
-}