diff --git a/src/browser/api/browser_view.ts b/src/browser/api/browser_view.ts index 472034e47..632d05d8e 100644 --- a/src/browser/api/browser_view.ts +++ b/src/browser/api/browser_view.ts @@ -104,10 +104,12 @@ export async function attach(ofView: OfView, toIdentity: Identity) { if (previousTarget.name !== toIdentity.name) { oldWin.browserWindow.removeBrowserView(view); of_events.emit(route.window('view-detached', previousTarget.uuid, previousTarget.name), { - viewIdentity: {uuid: ofView.uuid, name: ofView.name}, + name: ofView.name, + uuid: ofView.uuid, target: toIdentity, previousTarget }); + const oldwinMap = windowCloseListenerMap.get(oldWin); if (oldwinMap) { const listener = oldwinMap.get(ofView); if (typeof listener === 'function') { @@ -134,12 +136,15 @@ export async function attach(ofView: OfView, toIdentity: Identity) { windowCloseListenerMap.get(ofWin).set(ofView, listener); updateViewTarget(ofView, toIdentity); - of_events.emit(route.view('attached', ofView.uuid, ofView.name), { + of_events.emit(route.window('view-attached', toIdentity.uuid, toIdentity.name), { + name: ofView.name, + uuid: ofView.uuid, target: toIdentity, previousTarget }); - of_events.emit(route.window('view-attached', toIdentity.uuid, toIdentity.name), { - viewIdentity: {uuid: ofView.uuid, name: ofView.name}, + of_events.emit(route.view('target-changed', ofView.uuid, ofView.name), { + name: ofView.name, + uuid: ofView.uuid, target: toIdentity, previousTarget }); @@ -150,7 +155,7 @@ export async function destroy (ofView: OfView) { removeBrowserView(ofView); if (!view.isDestroyed()) { view.destroy(); - of_events.emit(route.view('destroyed', uuid, name), {target}); + of_events.emit(route.view('destroyed', uuid, name), {name, uuid, target}); } } diff --git a/src/browser/of_events.ts b/src/browser/of_events.ts index 892d9a420..092201323 100644 --- a/src/browser/of_events.ts +++ b/src/browser/of_events.ts @@ -1,7 +1,9 @@ + import { app } from 'electron'; import { EventEmitter } from 'events'; import { isFloat } from '../common/main'; import route from '../common/route'; +import {getBrowserViewByIdentity} from './core_state'; interface PastEvent { payload: any; @@ -33,6 +35,7 @@ class OFEvents extends EventEmitter { if (tokenizedRoute.length >= 2) { const [channel, topic] = tokenizedRoute; const uuid: string = (payload && payload.uuid) || tokenizedRoute[2] || '*'; + const name: string|undefined = (payload && payload.name); const source = tokenizedRoute.slice(2).join('/'); const envelope = { channel, topic, source, data }; const propagateToSystem = !topic.match(/-requested$/); @@ -55,7 +58,7 @@ class OFEvents extends EventEmitter { const dontPropagate = [ 'close-requested' ]; - if (!dontPropagate.some(t => t === topic)) { + if (!dontPropagate.some(t => t === topic) && !topic.startsWith('view')) { eventPropagations.set(route.application(propTopic, uuid), { ...checkedPayload, type: propTopic, @@ -67,11 +70,14 @@ class OFEvents extends EventEmitter { } } else if (channel === 'view') { const propTopic = `view-${topic}`; + this.propagateEventsToWindow(propTopic, checkedPayload, uuid, name, eventPropagations); + eventPropagations.set(route.application(propTopic, uuid), { ...checkedPayload, type: propTopic, topic: 'application' }); + if (propagateToSystem) { eventPropagations.set(route.system(propTopic), { ...checkedPayload, type: propTopic, topic: 'system' }); } @@ -146,6 +152,26 @@ class OFEvents extends EventEmitter { this.isSavingEvents = false; }, STARTUP_SAVE_EVENTS_DURATION); } + + private propagateEventsToWindow( + propTopic: string, checkedPayload: any, uuid: string, name: string|undefined, eventPropagations: Map) { + + let target; + if (name) { + const view = getBrowserViewByIdentity({ uuid, name }); + target = view && view.target; + } + + // Set the target in the checkedPayload, so that webcontents events have a target param in the payload. + target ? checkedPayload.target = target : target = checkedPayload.target; + if (target) { + eventPropagations.set(route.window(propTopic, target.uuid, target.name), { + ...checkedPayload, + type: propTopic, + topic: 'window' + }); + } + } } interface StringMap { diff --git a/test/errors.test.ts b/test/errors.test.ts index 926819305..8af7ae2ed 100644 --- a/test/errors.test.ts +++ b/test/errors.test.ts @@ -7,6 +7,8 @@ mockery.enable({ warnOnReplace: false, warnOnUnregistered: false }); +// Do not move this external_application mock - Core PR #976 +mockery.registerMock('./api/external_application', {}); import * as errors from '../src/common/errors'; describe('Errors', () => { diff --git a/test/event-propagation.ts b/test/event-propagation.ts index 7f6e32fce..978ca0c17 100644 --- a/test/event-propagation.ts +++ b/test/event-propagation.ts @@ -17,17 +17,20 @@ limitations under the License. import { mockElectron } from './electron'; import * as assert from 'assert'; import * as mockery from 'mockery'; -import ofEvents from '../src/browser/of_events'; import route from '../src/common/route'; const uuid = 'uuid4'; const name = 'name3'; mockery.registerMock('electron', mockElectron); +// Do not move this external_application mock - Core PR #976 +mockery.registerMock('./api/external_application', {}); mockery.enable({ warnOnReplace: false, warnOnUnregistered: false }); +// Do not move this ofEvents import - Core PR #976 +import ofEvents from '../src/browser/of_events'; describe('Event Propagation', function () { it('propagates window events to system', function (done) { diff --git a/test/file_download.ts b/test/file_download.ts index e1670ebd6..30a13fceb 100644 --- a/test/file_download.ts +++ b/test/file_download.ts @@ -1,7 +1,6 @@ import * as mockery from 'mockery'; import { mockElectron } from './electron'; import * as assert from 'assert'; -import ofEvents from '../src/browser/of_events'; import route from '../src/common/route'; import { EventEmitter } from 'events'; @@ -56,6 +55,8 @@ mockery.enable({ }); import { createWillDownloadEventListener, downloadLocationMap } from '../src/browser/api/file_download'; +// Do not move this ofEvents import - Core PR #976 +import ofEvents from '../src/browser/of_events'; describe('FileDownload', () => {