Wrap some native objects during event dispatch
This commit is contained in:
parent
2dc8319b50
commit
7ae4a5cb7e
@ -4,7 +4,9 @@
|
||||
#ifndef COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE
|
||||
#define COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE(ComponentWrapName) \
|
||||
\
|
||||
InstanceValue("type", Napi::String::New(env, "native")),
|
||||
InstanceValue("type", Napi::String::New(env, "native")), \
|
||||
InstanceValue("wrapperType", \
|
||||
Napi::String::New(env, #ComponentWrapName)),
|
||||
#endif
|
||||
|
||||
#ifndef COMPONENT_WRAPPED_METHODS_DECLARATION
|
||||
|
||||
@ -47,12 +47,10 @@ class DLL_EXPORT WrapperCache : public QObject {
|
||||
Napi::Object get(Napi::Env env, T* object) {
|
||||
if (this->cache.contains(object)) {
|
||||
napi_value result = nullptr;
|
||||
napi_get_reference_value(this->cache[object].env, this->cache[object].ref,
|
||||
&result);
|
||||
napi_get_reference_value(env, this->cache[object].ref, &result);
|
||||
return Napi::Object(env, result);
|
||||
}
|
||||
|
||||
Napi::HandleScope scope(env);
|
||||
Napi::Object wrapper =
|
||||
W::constructor.New({Napi::External<T>::New(env, object)});
|
||||
|
||||
@ -67,7 +65,6 @@ class DLL_EXPORT WrapperCache : public QObject {
|
||||
}
|
||||
|
||||
static Napi::Object init(Napi::Env env, Napi::Object exports) {
|
||||
Napi::HandleScope scope(env);
|
||||
exports.Set("WrapperCache_injectCallback",
|
||||
Napi::Function::New<injectDestroyCallback>(env));
|
||||
return exports;
|
||||
@ -75,7 +72,6 @@ class DLL_EXPORT WrapperCache : public QObject {
|
||||
|
||||
static Napi::Value injectDestroyCallback(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::HandleScope scope(env);
|
||||
|
||||
destroyedCallback = Napi::Persistent(info[0].As<Napi::Function>());
|
||||
return env.Null();
|
||||
@ -95,6 +91,7 @@ class DLL_EXPORT WrapperCache : public QObject {
|
||||
Napi::Env env = destroyedCallback.Env();
|
||||
Napi::HandleScope scope(env);
|
||||
destroyedCallback.Call(
|
||||
env.Global(),
|
||||
{Napi::Value::From(env, extrautils::hashPointerTo53bit(object))});
|
||||
}
|
||||
|
||||
|
||||
@ -168,7 +168,13 @@ export { FlexLayout, FlexLayoutSignals } from './lib/core/FlexLayout';
|
||||
// Others:
|
||||
export { StyleSheet } from './lib/core/Style/StyleSheet';
|
||||
export { NativeElement, Component } from './lib/core/Component';
|
||||
export { checkIfNativeElement, checkIfNapiExternal } from './lib/utils/helpers';
|
||||
export {
|
||||
checkIfNativeElement,
|
||||
checkIfNapiExternal,
|
||||
JsWrapFunction,
|
||||
registerNativeWrapFunction as registerNativeWrapper,
|
||||
wrapNative,
|
||||
} from './lib/utils/helpers';
|
||||
export { Margins } from './lib/utils/Margins';
|
||||
|
||||
// Test:
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { NativeElement } from '../core/Component';
|
||||
import { checkIfNativeElement } from '../utils/helpers';
|
||||
import { checkIfNativeElement, registerNativeWrapFunction } from '../utils/helpers';
|
||||
import { NodeObject, QObjectSignals } from '../QtCore/QObject';
|
||||
import { QRect } from '../QtCore/QRect';
|
||||
import { QSizeF } from '../QtCore/QSizeF';
|
||||
import { QSize } from '../QtCore/QSize';
|
||||
import { wrapperCache } from '../core/WrapperCache';
|
||||
|
||||
export class QScreen extends NodeObject<QScreenSignals> {
|
||||
native: NativeElement;
|
||||
@ -104,3 +105,7 @@ export interface QScreenSignals extends QObjectSignals {
|
||||
refreshRateChanged: (refreshRate: number) => void;
|
||||
virtualGeometryChanged: (rect: QRect) => void;
|
||||
}
|
||||
|
||||
registerNativeWrapFunction('QScreenWrap', (native: any) => {
|
||||
return wrapperCache.get<QScreen>(QScreen, native);
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { NativeElement } from '../core/Component';
|
||||
import { checkIfNativeElement } from '../utils/helpers';
|
||||
import { checkIfNativeElement, registerNativeWrapFunction } from '../utils/helpers';
|
||||
import { NodeObject, QObjectSignals } from '../QtCore/QObject';
|
||||
import { QScreen } from './QScreen';
|
||||
import { wrapperCache } from '../core/WrapperCache';
|
||||
@ -24,3 +24,7 @@ export class QWindow extends NodeObject<QWindowSignals> {
|
||||
export interface QWindowSignals extends QObjectSignals {
|
||||
screenChanged: (screen: QScreen) => void;
|
||||
}
|
||||
|
||||
registerNativeWrapFunction('QWindowWrap', (native: any) => {
|
||||
return wrapperCache.get<QWindow>(QWindow, native);
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { NativeElement, Component, NativeRawPointer } from './Component';
|
||||
import { wrapWithActivateUvLoop } from '../utils/helpers';
|
||||
import { wrapNative, wrapWithActivateUvLoop } from '../utils/helpers';
|
||||
|
||||
function addDefaultErrorHandler(native: NativeElement, emitter: EventEmitter): void {
|
||||
native.subscribeToQtEvent('error');
|
||||
@ -54,10 +54,11 @@ export abstract class EventWidget<Signals extends unknown> extends Component {
|
||||
// Preserve the value of `_isQObjectEventProcessed` as we dispatch this event
|
||||
// to JS land, and restore it afterwards. This lets us support recursive event
|
||||
// dispatches on the same object.
|
||||
const wrappedArgs = args.map(wrapNative);
|
||||
const previousEventProcessed = this._isEventProcessed;
|
||||
this._isEventProcessed = false;
|
||||
try {
|
||||
this.emitter.emit(event, ...args);
|
||||
this.emitter.emit(event, ...wrappedArgs);
|
||||
} catch (e) {
|
||||
console.log(`An exception was thrown while dispatching an event of type '${event.toString()}':`);
|
||||
console.log(e);
|
||||
|
||||
@ -25,3 +25,37 @@ export function wrapWithActivateUvLoop<T extends Function>(func: T): T {
|
||||
};
|
||||
return fn as any;
|
||||
}
|
||||
|
||||
export type JsWrapFunction = (element: any) => any;
|
||||
const nativeWrapperRegistry = new Map<string, JsWrapFunction>();
|
||||
|
||||
/**
|
||||
* Register a function to wrap a specific Node API wrapper objects with a JS object.
|
||||
*
|
||||
* @param wrapperTypeName the C++ wrapper type name the wrap function applies to.
|
||||
* @param jsWrapFunction function to wrap a native wrapper to a JS wrapper object.
|
||||
*/
|
||||
export function registerNativeWrapFunction(wrapperTypeName: string, jsWrapFunction: JsWrapFunction): void {
|
||||
nativeWrapperRegistry.set(wrapperTypeName, jsWrapFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to wrap a native Node object with its JS wrapper.
|
||||
*
|
||||
* @param native the native object to wrap
|
||||
* @return the JS object wrapping the native object or the native object if
|
||||
* it couldn't be wrapped or doesn't need to be wrapped.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export function wrapNative(native: any): any {
|
||||
if (!checkIfNativeElement(native)) {
|
||||
return native;
|
||||
}
|
||||
|
||||
const func: JsWrapFunction | undefined = nativeWrapperRegistry.get(native.wrapperType);
|
||||
if (func == null) {
|
||||
return native;
|
||||
}
|
||||
|
||||
return func(native);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user