]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventSink.java
Work around SWT 4.13 - 4.18 Win32 DnD bug 567422
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / ole / win32 / OleEventSink.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.ole.win32;
15
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.internal.*;
18 import org.eclipse.swt.internal.ole.win32.*;
19 import org.eclipse.swt.internal.win32.*;
20
21 final class OleEventSink
22 {
23         private OleControlSite widget;
24
25         private COMObject iDispatch;
26         private int refCount;
27
28         private IUnknown objIUnknown;
29         private int  eventCookie;
30         private GUID eventGuid;
31
32         private OleEventTable eventTable;
33
34 OleEventSink(OleControlSite widget, long iUnknown, GUID riid) {
35
36         this.widget = widget;
37         this.eventGuid = riid;
38         this.objIUnknown = new IUnknown(iUnknown);
39
40         createCOMInterfaces();
41 }
42
43 void connect () {
44         long[] ppvObject = new long[1];
45         if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
46                 IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
47                 long[] ppCP = new long[1];
48                 if (cpc.FindConnectionPoint(eventGuid, ppCP) == COM.S_OK) {
49                         IConnectionPoint cp = new IConnectionPoint(ppCP[0]);
50                         int[] pCookie = new int[1];
51                         if (cp.Advise(iDispatch.getAddress(), pCookie) == COM.S_OK)
52                                 eventCookie = pCookie[0];
53                         cp.Release();
54                 }
55                 cpc.Release();
56         }
57 }
58 void addListener(int eventID, OleListener listener) {
59         if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
60         if (eventTable == null) eventTable = new OleEventTable ();
61         eventTable.hook(eventID, listener);
62 }
63 int AddRef() {
64         refCount++;
65         return refCount;
66 }
67 private void createCOMInterfaces() {
68         iDispatch = new COMObject(new int[]{2, 0, 0, 1, 3, 4, 8}){
69                 @Override
70                 public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
71                 @Override
72                 public long method1(long[] args) {return AddRef();}
73                 @Override
74                 public long method2(long[] args) {return Release();}
75                 // method3 GetTypeInfoCount - not implemented
76                 // method4 GetTypeInfo - not implemented
77                 // method5 GetIDsOfNames - not implemented
78                 @Override
79                 public long method6(long[] args) {return Invoke((int)args[0], args[1], (int)args[2], (int)args[3], args[4], args[5], args[6], args[7]);}
80         };
81 }
82 void disconnect() {
83         // disconnect event sink
84         if (eventCookie != 0 && objIUnknown != null) {
85                 long[] ppvObject = new long[1];
86                 if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
87                         IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
88                         if (cpc.FindConnectionPoint(eventGuid, ppvObject) == COM.S_OK) {
89                                 IConnectionPoint cp = new IConnectionPoint(ppvObject[0]);
90                                 if (cp.Unadvise(eventCookie) == COM.S_OK) {
91                                         eventCookie = 0;
92                                 }
93                                 cp.Release();
94                         }
95                         cpc.Release();
96                 }
97         }
98 }
99 private void disposeCOMInterfaces() {
100         if (iDispatch != null)
101                 iDispatch.dispose();
102         iDispatch = null;
103
104 }
105 private int Invoke(int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr)
106 {
107         if (eventTable == null || !eventTable.hooks(dispIdMember)) return COM.S_OK;
108
109         // Construct an array of the parameters that are passed in
110         // Note: parameters are passed in reverse order - here we will correct the order
111         Variant[] eventInfo = null;
112         if (pDispParams != 0) {
113                 DISPPARAMS dispParams = new DISPPARAMS();
114                 COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof);
115                 eventInfo = new Variant[dispParams.cArgs];
116                 int size = VARIANT.sizeof;
117                 long offset = (dispParams.cArgs - 1) * size;
118
119                 for (int j = 0; j < dispParams.cArgs; j++){
120                         eventInfo[j] = new Variant();
121                         eventInfo[j].setData(dispParams.rgvarg + offset);
122                         offset = offset - size;
123                 }
124         }
125
126         OleEvent event = new OleEvent();
127         event.arguments = eventInfo;
128         notifyListener(dispIdMember,event);
129
130         if (eventInfo != null) {
131                 for (int j = 0; j < eventInfo.length; j++){
132                         eventInfo[j].dispose();
133                 }
134         }
135
136         return COM.S_OK;
137 }
138 /**
139 * Notify listeners of an event.
140 * <p>
141 *       This method notifies all listeners that an event
142 * has occurred.
143 *
144 * @param eventType the desired SWT event
145 * @param event the event data
146 *
147 * @exception IllegalArgumentException <ul>
148 *               <li>ERROR_NULL_ARGUMENT when handler is null</li>
149 * </ul>
150 * @exception SWTException <ul>
151 *               <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
152 *               <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
153 *       </ul>
154 */
155 private void notifyListener (int eventType, OleEvent event) {
156         if (event == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
157         if (eventTable == null) return;
158         event.type = eventType;
159         event.widget = widget;
160         eventTable.sendEvent (event);
161 }
162 private int QueryInterface(long riid, long ppvObject) {
163
164         if (riid == 0 || ppvObject == 0)
165                 return COM.E_INVALIDARG;
166         GUID guid = new GUID();
167         COM.MoveMemory(guid, riid, GUID.sizeof);
168
169         if ( COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) ||
170                         COM.IsEqualGUID(guid, eventGuid)) {
171                 OS.MoveMemory(ppvObject, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
172                 AddRef();
173                 return OLE.S_OK;
174         }
175
176         OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
177         return COM.E_NOINTERFACE;
178 }
179 int Release() {
180         refCount--;
181         if (refCount == 0) {
182                 disposeCOMInterfaces();
183         }
184
185         return refCount;
186 }
187 void removeListener(int eventID, OleListener listener) {
188         if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
189         if (eventTable == null) return;
190         eventTable.unhook (eventID, listener);
191 }
192 boolean hasListeners() {
193         return eventTable.hasEntries();
194 }
195 }