4
4
5
5
/* **** HELPERS *****/
6
6
7
+ // Converts a CGError to a human-readable string.
8
+ std::string CGErrorToString (CGError err) {
9
+ if (err == kCGErrorCannotComplete ) {
10
+ return " The requested operation is inappropriate for the parameters passed "
11
+ " in, or the current system state" ;
12
+ } else if (err == kCGErrorFailure ) {
13
+ return " A general failure occurred" ;
14
+ } else if (err == kCGErrorIllegalArgument ) {
15
+ return " One or more of the parameters passed to a function are invalid" ;
16
+ } else if (err == kCGErrorInvalidConnection ) {
17
+ return " The parameter representing a connection to the window server is "
18
+ " invalid" ;
19
+ } else if (err == kCGErrorInvalidContext ) {
20
+ return " The CPSProcessSerNum or context identifier parameter is not valid" ;
21
+ } else if (err == kCGErrorInvalidOperation ) {
22
+ return " The requested operation is not valid for the parameters passed in, "
23
+ " or the current system state." ;
24
+ } else if (err == kCGErrorNoneAvailable ) {
25
+ return " The requested operation could not be completed as the indicated "
26
+ " resources were not found" ;
27
+ } else if (err == kCGErrorNotImplemented ) {
28
+ return " Return value from obsolete function stubs present for binary "
29
+ " compatibility, but not typically called" ;
30
+ } else if (err == kCGErrorRangeCheck ) {
31
+ return " A parameter passed in has a value that is inappropriate, or which "
32
+ " does not map to a useful operation or value" ;
33
+ } else if (err == kCGErrorTypeCheck ) {
34
+ return " A data type or token was encountered that did not match the "
35
+ " expected type or token" ;
36
+ } else {
37
+ return " Unknown display configuration error" ;
38
+ }
39
+ }
40
+
7
41
// Converts a simple C array to a Napi::Array.
8
42
template <typename T> Napi::Array CArrayToNapiArray (Napi::Env env, T *c_arr) {
9
43
Napi::Array arr = Napi::Array::New (env, sizeof c_arr);
@@ -191,6 +225,45 @@ bool GetIsMonochrome() {
191
225
return Napi::Object ();
192
226
}
193
227
228
+ // Configure two macOS system displays to mirror status.
229
+ void Mirror (const Napi::CallbackInfo &info) {
230
+ bool enable = info[0 ].As <Napi::Boolean >().Value ();
231
+
232
+ uint32_t primary_display_id;
233
+ uint32_t secondary_display_id;
234
+ if (info.Length () == 3 ) {
235
+ primary_display_id = info[1 ].As <Napi::Number>().Uint32Value ();
236
+ secondary_display_id = info[2 ].As <Napi::Number>().Uint32Value ();
237
+ } else {
238
+ primary_display_id = CGMainDisplayID ();
239
+ secondary_display_id = info[1 ].As <Napi::Number>().Uint32Value ();
240
+ }
241
+
242
+ CGDisplayConfigRef config_ref;
243
+ CGError err = CGBeginDisplayConfiguration (&config_ref);
244
+ if (err != 0 ) {
245
+ Napi::Error::New (info.Env (), CGErrorToString (err))
246
+ .ThrowAsJavaScriptException ();
247
+ return ;
248
+ }
249
+
250
+ err = CGConfigureDisplayMirrorOfDisplay (config_ref, secondary_display_id,
251
+ enable ? primary_display_id
252
+ : kCGNullDirectDisplay );
253
+ if (err != 0 ) {
254
+ Napi::Error::New (info.Env (), CGErrorToString (err))
255
+ .ThrowAsJavaScriptException ();
256
+ return ;
257
+ }
258
+
259
+ err = CGCompleteDisplayConfiguration (config_ref, kCGConfigurePermanently );
260
+ if (err != 0 ) {
261
+ Napi::Error::New (info.Env (), CGErrorToString (err))
262
+ .ThrowAsJavaScriptException ();
263
+ return ;
264
+ }
265
+ }
266
+
194
267
// Initializes all functions exposed to JS.
195
268
Napi::Object Init (Napi::Env env, Napi::Object exports) {
196
269
exports.Set (Napi::String::New (env, " getAllDisplays" ),
@@ -199,6 +272,8 @@ bool GetIsMonochrome() {
199
272
Napi::Function::New (env, GetPrimaryDisplay));
200
273
exports.Set (Napi::String::New (env, " getDisplayFromID" ),
201
274
Napi::Function::New (env, GetDisplayFromID));
275
+ exports.Set (Napi::String::New (env, " mirror" ),
276
+ Napi::Function::New (env, Mirror));
202
277
exports.Set (Napi::String::New (env, " screenshot" ),
203
278
Napi::Function::New (env, Screenshot));
204
279
0 commit comments