66#include < shellapi.h>
77#include < wil/win32_helpers.h>
88
9- const wchar_t * scriptOnLoad =
10- LR"(
11- (function() {
12- window.wdw = { "inClick": false/*, "inSubmit": false, "inKeydown": false*/ };
13- function syncScroll(e) {
14- var el = document.querySelector(e.selector);
15- if (el && getWindowLocation() === e.window) {
16- var sleft = Math.round((el.scrollWidth - el.clientWidth) * e.left);
17- var stop = Math.round((el.scrollHeight - el.clientHeight) * e.top);
18- clearTimeout(wdw.timeout);
19- wdw.timeout = setTimeout(function() {
20- if (el.scroll)
21- {
22- window.removeEventListener('scroll', onScroll, true);
23- el.scroll(sleft, stop);
24- setTimeout(function() { window.addEventListener('scroll', onScroll, true); }, 10);
25- }
26- }, 100);
27- }
28- }
29- function syncClick(e) {
30- var el = document.querySelector(e.selector);
31- if (el && getWindowLocation() === e.window) {
32- wdw.inClick = true;
33- if (el.click)
34- el.click();
35- wdw.inClick = false;
36- }
37- }
38- function syncInput(e) {
39- var el = document.querySelector(e.selector);
40- if (el && getWindowLocation() === e.window) {
41- el.value = e.value;
42- }
43- }
44- /*
45- function syncSubmit(e) {
46- var el = document.querySelector(e.selector);
47- if (el && getWindowLocation() === e.window) {
48- wdw.inSubmit = true;
49- if (el.submit)
50- el.submit();
51- wdw.inSubmit = false;
52- }
53- }
54- function syncKeydown(e) {
55- var el = document.querySelector(e.selector);
56- if (el && getWindowLocation() === e.window) {
57- wdw.inKeydown = true;
58- var ev = new KeyboardEvent("keydown", e);
59- if (el.dispatchEvent)
60- el.dispatchEvent(ev);
61- wdw.inKeydown = false;
62- }
63- }
64- */
65- function getWindowLocation() {
66- let locationString = '';
67- let currentWindow = window;
68-
69- while (currentWindow !== window.top) {
70- const frames = currentWindow.parent.frames;
71- let index = -1;
72- for (let i = 0; i < frames.length; i++) {
73- if (frames[i] === currentWindow) {
74- index = i;
75- break;
76- }
77- }
78- if (index !== -1) {
79- locationString = `[${index}]` + locationString;
80- } else {
81- locationString = 'top' + locationString;
82- }
83- currentWindow = currentWindow.parent;
84- }
85-
86- return locationString;
87- }
88- function getElementSelector(element) {
89- if (!(element instanceof Element)) {
90- return null;
91- }
92-
93- const selectorList = [];
94- while (element.parentNode) {
95- let nodeName = element.nodeName.toLowerCase();
96- if (element.id) {
97- selectorList.unshift(`#${element.id}`);
98- break;
99- } else {
100- let sibCount = 0;
101- let sibIndex = 0;
102- const siblings = element.parentNode.childNodes;
103- for (let i = 0; i < siblings.length; i++) {
104- const sibling = siblings[i];
105- if (sibling.nodeType === 1) {
106- if (sibling === element) {
107- sibIndex = sibCount;
108- }
109- if (sibling.nodeName.toLowerCase() === nodeName) {
110- sibCount++;
111- }
112- }
113- }
114- if (sibIndex > 0) {
115- nodeName += `:nth-of-type(${sibIndex + 1})`;
116- }
117- selectorList.unshift(nodeName);
118- element = element.parentNode;
119- }
120- }
121- return selectorList.join(' > ');
122- }
123- function onScroll(e) {
124- var el = ('scrollingElement' in e.target) ? e.target.scrollingElement : e.target;
125- var sel = getElementSelector(el);
126- var msg = {
127- "event": "scroll",
128- "window": getWindowLocation(),
129- "selector": sel,
130- "left": ((el.scrollWidth == el.clientWidth) ? 0 : (el.scrollLeft / (el.scrollWidth - el.clientWidth))),
131- "top": ((el.scrollHeight == el.clientHeight) ? 0 : (el.scrollTop / (el.scrollHeight - el.clientHeight)))
132- };
133- window.chrome.webview.postMessage(JSON.stringify(msg));
134- }
135- function onClick(e) {
136- if (wdw.inClick)
137- return;
138- var sel = getElementSelector(e.target);
139- var msg = { "event": "click", "window": getWindowLocation(), "selector": sel };
140- window.chrome.webview.postMessage(JSON.stringify(msg));
141- }
142- function onInput(e) {
143- var sel = getElementSelector(e.target);
144- var msg = { "event": "input", "window": getWindowLocation(), "selector": sel, "value": e.target.value };
145- window.chrome.webview.postMessage(JSON.stringify(msg));
146- }
147- function onDblClick(e) {
148- var el = e.target;
149- var sel = getElementSelector(el);
150- var wwdid = ('wwdid' in el.dataset) ? el.dataset['wwdid'] : (('wwdid' in el.parentElement.dataset) ? el.parentElement.dataset['wwdid'] : -1);
151- var msg = { "event": "dblclick", "window": getWindowLocation(), "selector": sel, "wwdid": parseInt(wwdid) };
152- window.chrome.webview.postMessage(JSON.stringify(msg));
153- }
154- function onMessage(arg) {
155- var data = arg.data;
156- switch (data.event) {
157- case "scroll":
158- syncScroll(data);
159- break;
160- case "click":
161- syncClick(data);
162- break;
163- case "input":
164- syncInput(data);
165- break;
166- /*
167- case "submit":
168- syncSubmit(data);
169- break;
170- case "keydown":
171- syncKeydown(data);
172- break;
173- */
174- }
175- }
176- window.addEventListener('click', onClick, true);
177- window.addEventListener('input', onInput, true);
178- window.addEventListener('dblclick', onDblClick, true);
179- window.addEventListener('scroll', onScroll, true);
180- window.chrome.webview.addEventListener('message', onMessage);
181- /*
182- var forms = document.querySelectorAll('form');
183- forms.forEach(function(form) {
184- form.addEventListener('submit', function(e) {
185- if (wdw.inSubmit)
186- return;
187- var sel = getElementSelector(e.target);
188- var msg = { "event": "submit", "window": getWindowLocation(), "selector": sel };
189- window.chrome.webview.postMessage(JSON.stringify(msg));
190- });
191- }, true);
192- window.addEventListener('keydown', function(e) {
193- if (wdw.inKeydown)
194- return;
195- var sel = getElementSelector(e.target);
196- var msg = { "event": "keydown", "window": getWindowLocation(), "selector": sel, "altKey": e.altKey, "code": e.code, "ctrlKey": e.ctrlKey, "isComposing": e.isComposing, "key": e.key, "locale": e.locale, "location": e.location, "metaKey": e.metaKey, "repeat": e.repeat, "shiftKey": e.shiftKey };
197- window.chrome.webview.postMessage(JSON.stringify(msg));
198- }, true);
199- */
200- })();
201- )" ;
202-
2039class CWebDiffWindow : public IWebDiffWindow
20410{
20511public:
@@ -359,6 +165,11 @@ class CWebDiffWindow : public IWebDiffWindow
359165 else if (event == WebDiffEvent::WebMessageReceived || event == WebDiffEvent::FrameWebMessageReceived)
360166 {
361167 std::wstring msg = m_webWindow[i].GetWebMessage ();
168+ #ifdef _DEBUG
169+ wchar_t buf[4096 ];
170+ wsprintfW (buf, L" WebMessageReceived(pane:%d): %s\n " , ev.pane , msg.c_str ());
171+ OutputDebugString (buf);
172+ #endif
362173 WDocument doc;
363174 doc.Parse (msg.c_str ());
364175 std::wstring event = doc.HasMember (L" event" ) ? doc[L" event" ].GetString () : L" " ;
@@ -1009,7 +820,7 @@ class CWebDiffWindow : public IWebDiffWindow
1009820
1010821 HRESULT addEventListener (IUnknown* sender, int pane, IWebDiffCallback* callback)
1011822 {
1012- return m_webWindow[pane].ExecuteScript (sender, scriptOnLoad , callback);
823+ return m_webWindow[pane].ExecuteScript (sender, GetScriptOnLoad () , callback);
1013824 }
1014825
1015826 HRESULT syncEvent (int srcPane, const std::wstring& json)
@@ -1629,6 +1440,21 @@ class CWebDiffWindow : public IWebDiffWindow
16291440 return fp != nullptr ? S_OK : (GetLastError () == 0 ? E_FAIL : HRESULT_FROM_WIN32 (GetLastError ()));
16301441 }
16311442
1443+ static wchar_t * GetScriptOnLoad ()
1444+ {
1445+ LPVOID pData = nullptr ;
1446+ HMODULE hModule = GetModuleHandle (L" WinWebDiffLib.dll" );
1447+ HRSRC hResource = FindResource (hModule, MAKEINTRESOURCE (IDR_SCRIPT), RT_RCDATA);
1448+ if (hResource) {
1449+ HGLOBAL hLoadedResource = LoadResource (hModule, hResource);
1450+ if (hLoadedResource) {
1451+ pData = LockResource (hLoadedResource);
1452+ FreeResource (hLoadedResource);
1453+ }
1454+ }
1455+ return reinterpret_cast <wchar_t *>(pData) + 1 /* bom*/ ;
1456+ }
1457+
16321458 int m_nPanes = 0 ;
16331459 HWND m_hWnd = nullptr ;
16341460 HINSTANCE m_hInstance = nullptr ;
@@ -1651,7 +1477,6 @@ class CWebDiffWindow : public IWebDiffWindow
16511477 bool m_bShowDifferences = true ;
16521478 bool m_bShowWordDifferences = true ;
16531479 bool m_bSynchronizeEvents = true ;
1654- bool m_bCompareCompleted = false ;
16551480 unsigned m_eventSyncFlags = EVENT_SCROLL | EVENT_CLICK | EVENT_INPUT | EVENT_GOBACKFORWARD;
16561481 CompareState m_compareState = NOT_COMPARED;
16571482 IWebDiffWindow::ColorSettings m_colorSettings = {
0 commit comments