@bun-native/protocol 0.33.0 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bun-native-source.json +30 -30
- package/package.json +1 -1
- package/src/app-menu.ts +20 -12
- package/src/dialogs.ts +21 -6
- package/src/drops.ts +4 -2
- package/src/elements.ts +76 -47
- package/src/files.ts +26 -12
- package/src/framing.ts +33 -9
- package/src/index.ts +10 -24
- package/src/message-dialogs.ts +22 -16
- package/src/messages.ts +181 -79
- package/src/processes.ts +19 -8
- package/src/services.ts +30 -19
- package/src/values.ts +8 -2
package/src/messages.ts
CHANGED
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
type DropRejection,
|
|
76
76
|
} from './drops.ts'
|
|
77
77
|
import {
|
|
78
|
+
fields,
|
|
78
79
|
id,
|
|
79
80
|
integer,
|
|
80
81
|
keys,
|
|
@@ -85,8 +86,9 @@ import {
|
|
|
85
86
|
string,
|
|
86
87
|
} from './values.ts'
|
|
87
88
|
|
|
88
|
-
export const PROTOCOL_VERSION =
|
|
89
|
-
|
|
89
|
+
export const PROTOCOL_VERSION = 12
|
|
90
|
+
/** Four operations per node of a full window: a whole-window replacement fits one batch. */
|
|
91
|
+
export const MAX_OPERATIONS = 16_384
|
|
90
92
|
const MAX_NODES_PER_WINDOW = 4_096
|
|
91
93
|
const MAX_WINDOWS = 16
|
|
92
94
|
const MAX_DEPTH = 64
|
|
@@ -614,24 +616,41 @@ export type NativeEvent =
|
|
|
614
616
|
/** Application-scoped: a menu bar belongs to the application, not a window. */
|
|
615
617
|
| { type: 'app_menu_item'; sequence: number; menu_id: number; item_id: string }
|
|
616
618
|
| { type: 'error'; id?: number; code: ErrorCode; message: string }
|
|
619
|
+
/** Sequenced events owned by one window. */
|
|
620
|
+
export type WindowEvent = Extract<NativeEvent, { sequence: number; window_id: number }>
|
|
621
|
+
/** Sequenced events owned by the application rather than one window. */
|
|
622
|
+
export type ApplicationEvent = Extract<NativeEvent, { type: 'app_menu_item' }>
|
|
623
|
+
/** Unsolicited events, as opposed to responses that carry a request id. */
|
|
624
|
+
export type HostEvent = WindowEvent | ApplicationEvent
|
|
617
625
|
|
|
618
626
|
function version(value: unknown): typeof PROTOCOL_VERSION {
|
|
619
627
|
if (value !== PROTOCOL_VERSION) throw new ProtocolError('Native protocol version mismatch')
|
|
620
628
|
return PROTOCOL_VERSION
|
|
621
629
|
}
|
|
622
630
|
|
|
631
|
+
/** Property names of a window-scoped command, reply or unsolicited event. */
|
|
632
|
+
const windowCommand = (...names: string[]) => fields('id', 'type', 'window_id', ...names)
|
|
633
|
+
const windowReply = (...names: string[]) => fields('type', 'id', 'window_id', ...names)
|
|
634
|
+
const windowNotice = (...names: string[]) => fields('type', 'sequence', 'window_id', ...names)
|
|
635
|
+
|
|
636
|
+
const OPERATION_CREATE_KEYS = fields('type', 'node_id', 'element')
|
|
637
|
+
const OPERATION_SET_KEYS = fields('type', 'node_id', 'element', 'expected_input_revision')
|
|
638
|
+
const OPERATION_INSERT_KEYS = fields('type', 'parent_id', 'child_id', 'index')
|
|
639
|
+
const OPERATION_DELETE_KEYS = fields('type', 'node_id')
|
|
640
|
+
const OPERATION_SCROLL_TO_KEYS = fields('type', 'node_id', 'x', 'y')
|
|
641
|
+
|
|
623
642
|
function operation(value: unknown): Operation {
|
|
624
643
|
const data = object(value)
|
|
625
644
|
switch (data['type']) {
|
|
626
645
|
case 'create':
|
|
627
|
-
keys(data,
|
|
646
|
+
keys(data, OPERATION_CREATE_KEYS)
|
|
628
647
|
return {
|
|
629
648
|
type: 'create',
|
|
630
649
|
node_id: id(data['node_id']),
|
|
631
650
|
element: parseElement(data['element']),
|
|
632
651
|
}
|
|
633
652
|
case 'set': {
|
|
634
|
-
keys(data,
|
|
653
|
+
keys(data, OPERATION_SET_KEYS)
|
|
635
654
|
const node_id = id(data['node_id'])
|
|
636
655
|
const element = parseElement(data['element'])
|
|
637
656
|
if (element.kind === 'input')
|
|
@@ -646,7 +665,7 @@ function operation(value: unknown): Operation {
|
|
|
646
665
|
return { type: 'set', node_id, element }
|
|
647
666
|
}
|
|
648
667
|
case 'insert':
|
|
649
|
-
keys(data,
|
|
668
|
+
keys(data, OPERATION_INSERT_KEYS)
|
|
650
669
|
return {
|
|
651
670
|
type: 'insert',
|
|
652
671
|
parent_id: id(data['parent_id']),
|
|
@@ -656,10 +675,10 @@ function operation(value: unknown): Operation {
|
|
|
656
675
|
case 'delete':
|
|
657
676
|
case 'focus':
|
|
658
677
|
case 'scroll_into_view':
|
|
659
|
-
keys(data,
|
|
678
|
+
keys(data, OPERATION_DELETE_KEYS)
|
|
660
679
|
return { type: data['type'], node_id: id(data['node_id']) }
|
|
661
680
|
case 'scroll_to': {
|
|
662
|
-
keys(data,
|
|
681
|
+
keys(data, OPERATION_SCROLL_TO_KEYS)
|
|
663
682
|
if (!('x' in data) && !('y' in data)) throw new ProtocolError('scroll_to requires x or y')
|
|
664
683
|
const offset = (axis: 'x' | 'y') =>
|
|
665
684
|
axis in data ? { [axis]: number(data[axis], 'scroll ' + axis, 0, MAX_SCROLL_OFFSET) } : {}
|
|
@@ -670,20 +689,50 @@ function operation(value: unknown): Operation {
|
|
|
670
689
|
}
|
|
671
690
|
}
|
|
672
691
|
|
|
692
|
+
const COMMAND_HELLO_KEYS = fields('id', 'type', 'protocol')
|
|
693
|
+
const COMMAND_OPEN_KEYS = windowCommand('root_id', 'title', 'width', 'height')
|
|
694
|
+
const COMMAND_BATCH_KEYS = windowCommand('base_revision', 'operations')
|
|
695
|
+
const COMMAND_CLOSE_KEYS = windowCommand()
|
|
696
|
+
const COMMAND_CLIPBOARD_WRITE_KEYS = windowCommand('text')
|
|
697
|
+
const COMMAND_REGISTER_GLOBAL_SHORTCUT_KEYS = windowCommand('shortcut_id', 'key', 'modifiers')
|
|
698
|
+
const COMMAND_UNREGISTER_GLOBAL_SHORTCUT_KEYS = windowCommand('shortcut_id')
|
|
699
|
+
const COMMAND_POST_NOTIFICATION_KEYS = windowCommand('notification_id', 'title', 'body')
|
|
700
|
+
const COMMAND_WITHDRAW_NOTIFICATION_KEYS = windowCommand('notification_id')
|
|
701
|
+
const COMMAND_OPEN_FILE_GRANT_KEYS = windowCommand('grant_id', 'root', 'access')
|
|
702
|
+
const COMMAND_CLOSE_FILE_GRANT_KEYS = windowCommand('grant_id')
|
|
703
|
+
const COMMAND_FILE_REQUEST_KEYS = windowCommand('grant_id', 'path', 'operation')
|
|
704
|
+
const COMMAND_SPAWN_PROCESS_KEYS = windowCommand('process_id', 'launch')
|
|
705
|
+
const COMMAND_WRITE_PROCESS_KEYS = windowCommand('process_id', 'data')
|
|
706
|
+
const COMMAND_CLOSE_PROCESS_INPUT_KEYS = windowCommand('process_id')
|
|
707
|
+
const COMMAND_RESIZE_PROCESS_KEYS = windowCommand('process_id', 'size')
|
|
708
|
+
const COMMAND_SIGNAL_PROCESS_KEYS = windowCommand('process_id', 'signal')
|
|
709
|
+
const COMMAND_ACKNOWLEDGE_PROCESS_OUTPUT_KEYS = windowCommand('process_id', 'chunk')
|
|
710
|
+
const COMMAND_SHOW_FILE_DIALOG_KEYS = windowCommand('dialog_id', 'options')
|
|
711
|
+
const COMMAND_CLOSE_FILE_DIALOG_KEYS = windowCommand('dialog_id')
|
|
712
|
+
const COMMAND_SHOW_MESSAGE_DIALOG_KEYS = windowCommand('dialog_id', 'options')
|
|
713
|
+
const COMMAND_CLOSE_MESSAGE_DIALOG_KEYS = windowCommand('dialog_id')
|
|
714
|
+
const COMMAND_SHOW_CONTEXT_MENU_KEYS = windowCommand('menu_id', 'x', 'y', 'items')
|
|
715
|
+
const COMMAND_CLOSE_CONTEXT_MENU_KEYS = windowCommand('menu_id')
|
|
716
|
+
const COMMAND_REGISTER_DROP_TARGET_KEYS = windowCommand('target_id', 'node_id')
|
|
717
|
+
const COMMAND_UNREGISTER_DROP_TARGET_KEYS = windowCommand('target_id')
|
|
718
|
+
const COMMAND_RESOLVE_DROPPED_ITEM_KEYS = windowCommand('target_id', 'drop_id', 'item', 'root')
|
|
719
|
+
const COMMAND_SET_APP_MENU_KEYS = fields('id', 'type', 'menu_id', 'menus')
|
|
720
|
+
const COMMAND_SHUTDOWN_KEYS = fields('id', 'type')
|
|
721
|
+
|
|
673
722
|
/** Validate before crossing the native boundary, including JavaScript callers. */
|
|
674
723
|
export function parseCommand(value: unknown): Command {
|
|
675
724
|
const message = object(value)
|
|
676
725
|
const request = id(message['id'])
|
|
677
726
|
switch (message['type']) {
|
|
678
727
|
case 'hello':
|
|
679
|
-
keys(message,
|
|
728
|
+
keys(message, COMMAND_HELLO_KEYS)
|
|
680
729
|
return {
|
|
681
730
|
id: request,
|
|
682
731
|
type: 'hello',
|
|
683
732
|
protocol: version(message['protocol']),
|
|
684
733
|
}
|
|
685
734
|
case 'open': {
|
|
686
|
-
keys(message,
|
|
735
|
+
keys(message, COMMAND_OPEN_KEYS)
|
|
687
736
|
const title = string(message['title'], 'title', MAX_TITLE_BYTES)
|
|
688
737
|
if (!title || /\p{Cc}/u.test(title))
|
|
689
738
|
throw new ProtocolError('Window title must be nonempty and contain no control characters')
|
|
@@ -698,7 +747,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
698
747
|
}
|
|
699
748
|
}
|
|
700
749
|
case 'batch': {
|
|
701
|
-
keys(message,
|
|
750
|
+
keys(message, COMMAND_BATCH_KEYS)
|
|
702
751
|
const operations = message['operations']
|
|
703
752
|
if (!Array.isArray(operations) || operations.length < 1 || operations.length > MAX_OPERATIONS)
|
|
704
753
|
throw new ProtocolError(
|
|
@@ -715,14 +764,14 @@ export function parseCommand(value: unknown): Command {
|
|
|
715
764
|
case 'close':
|
|
716
765
|
case 'display_snapshot':
|
|
717
766
|
case 'clipboard_read':
|
|
718
|
-
keys(message,
|
|
767
|
+
keys(message, COMMAND_CLOSE_KEYS)
|
|
719
768
|
return {
|
|
720
769
|
id: request,
|
|
721
770
|
type: message['type'],
|
|
722
771
|
window_id: id(message['window_id']),
|
|
723
772
|
}
|
|
724
773
|
case 'clipboard_write':
|
|
725
|
-
keys(message,
|
|
774
|
+
keys(message, COMMAND_CLIPBOARD_WRITE_KEYS)
|
|
726
775
|
return {
|
|
727
776
|
id: request,
|
|
728
777
|
type: 'clipboard_write',
|
|
@@ -730,7 +779,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
730
779
|
text: string(message['text'], 'clipboard text', MAX_CLIPBOARD_BYTES),
|
|
731
780
|
}
|
|
732
781
|
case 'register_global_shortcut':
|
|
733
|
-
keys(message,
|
|
782
|
+
keys(message, COMMAND_REGISTER_GLOBAL_SHORTCUT_KEYS)
|
|
734
783
|
return {
|
|
735
784
|
id: request,
|
|
736
785
|
type: 'register_global_shortcut',
|
|
@@ -740,7 +789,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
740
789
|
modifiers: parseShortcutModifiers(message['modifiers']),
|
|
741
790
|
}
|
|
742
791
|
case 'unregister_global_shortcut':
|
|
743
|
-
keys(message,
|
|
792
|
+
keys(message, COMMAND_UNREGISTER_GLOBAL_SHORTCUT_KEYS)
|
|
744
793
|
return {
|
|
745
794
|
id: request,
|
|
746
795
|
type: 'unregister_global_shortcut',
|
|
@@ -748,7 +797,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
748
797
|
shortcut_id: id(message['shortcut_id']),
|
|
749
798
|
}
|
|
750
799
|
case 'post_notification': {
|
|
751
|
-
keys(message,
|
|
800
|
+
keys(message, COMMAND_POST_NOTIFICATION_KEYS)
|
|
752
801
|
const { title, body } = parseNotificationContent(message['title'], message['body'])
|
|
753
802
|
return {
|
|
754
803
|
id: request,
|
|
@@ -760,7 +809,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
760
809
|
}
|
|
761
810
|
}
|
|
762
811
|
case 'withdraw_notification':
|
|
763
|
-
keys(message,
|
|
812
|
+
keys(message, COMMAND_WITHDRAW_NOTIFICATION_KEYS)
|
|
764
813
|
return {
|
|
765
814
|
id: request,
|
|
766
815
|
type: 'withdraw_notification',
|
|
@@ -768,7 +817,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
768
817
|
notification_id: id(message['notification_id']),
|
|
769
818
|
}
|
|
770
819
|
case 'open_file_grant':
|
|
771
|
-
keys(message,
|
|
820
|
+
keys(message, COMMAND_OPEN_FILE_GRANT_KEYS)
|
|
772
821
|
return {
|
|
773
822
|
id: request,
|
|
774
823
|
type: 'open_file_grant',
|
|
@@ -778,7 +827,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
778
827
|
access: parseFileAccess(message['access']),
|
|
779
828
|
}
|
|
780
829
|
case 'close_file_grant':
|
|
781
|
-
keys(message,
|
|
830
|
+
keys(message, COMMAND_CLOSE_FILE_GRANT_KEYS)
|
|
782
831
|
return {
|
|
783
832
|
id: request,
|
|
784
833
|
type: 'close_file_grant',
|
|
@@ -786,7 +835,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
786
835
|
grant_id: id(message['grant_id']),
|
|
787
836
|
}
|
|
788
837
|
case 'file_request': {
|
|
789
|
-
keys(message,
|
|
838
|
+
keys(message, COMMAND_FILE_REQUEST_KEYS)
|
|
790
839
|
const path = parseFilePath(message['path'])
|
|
791
840
|
return {
|
|
792
841
|
id: request,
|
|
@@ -798,7 +847,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
798
847
|
}
|
|
799
848
|
}
|
|
800
849
|
case 'spawn_process':
|
|
801
|
-
keys(message,
|
|
850
|
+
keys(message, COMMAND_SPAWN_PROCESS_KEYS)
|
|
802
851
|
return {
|
|
803
852
|
id: request,
|
|
804
853
|
type: 'spawn_process',
|
|
@@ -807,7 +856,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
807
856
|
launch: parseProcessLaunch(message['launch']),
|
|
808
857
|
}
|
|
809
858
|
case 'write_process':
|
|
810
|
-
keys(message,
|
|
859
|
+
keys(message, COMMAND_WRITE_PROCESS_KEYS)
|
|
811
860
|
return {
|
|
812
861
|
id: request,
|
|
813
862
|
type: 'write_process',
|
|
@@ -817,7 +866,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
817
866
|
}
|
|
818
867
|
case 'close_process_input':
|
|
819
868
|
case 'release_process':
|
|
820
|
-
keys(message,
|
|
869
|
+
keys(message, COMMAND_CLOSE_PROCESS_INPUT_KEYS)
|
|
821
870
|
return {
|
|
822
871
|
id: request,
|
|
823
872
|
type: message['type'],
|
|
@@ -825,7 +874,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
825
874
|
process_id: id(message['process_id']),
|
|
826
875
|
}
|
|
827
876
|
case 'resize_process':
|
|
828
|
-
keys(message,
|
|
877
|
+
keys(message, COMMAND_RESIZE_PROCESS_KEYS)
|
|
829
878
|
return {
|
|
830
879
|
id: request,
|
|
831
880
|
type: 'resize_process',
|
|
@@ -834,7 +883,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
834
883
|
size: parseTerminalSize(message['size']),
|
|
835
884
|
}
|
|
836
885
|
case 'signal_process':
|
|
837
|
-
keys(message,
|
|
886
|
+
keys(message, COMMAND_SIGNAL_PROCESS_KEYS)
|
|
838
887
|
return {
|
|
839
888
|
id: request,
|
|
840
889
|
type: 'signal_process',
|
|
@@ -843,7 +892,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
843
892
|
signal: parseProcessSignal(message['signal']),
|
|
844
893
|
}
|
|
845
894
|
case 'acknowledge_process_output':
|
|
846
|
-
keys(message,
|
|
895
|
+
keys(message, COMMAND_ACKNOWLEDGE_PROCESS_OUTPUT_KEYS)
|
|
847
896
|
return {
|
|
848
897
|
id: request,
|
|
849
898
|
type: 'acknowledge_process_output',
|
|
@@ -852,7 +901,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
852
901
|
chunk: id(message['chunk']),
|
|
853
902
|
}
|
|
854
903
|
case 'show_file_dialog':
|
|
855
|
-
keys(message,
|
|
904
|
+
keys(message, COMMAND_SHOW_FILE_DIALOG_KEYS)
|
|
856
905
|
return {
|
|
857
906
|
id: request,
|
|
858
907
|
type: 'show_file_dialog',
|
|
@@ -861,7 +910,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
861
910
|
options: parseFileDialogOptions(message['options']),
|
|
862
911
|
}
|
|
863
912
|
case 'close_file_dialog':
|
|
864
|
-
keys(message,
|
|
913
|
+
keys(message, COMMAND_CLOSE_FILE_DIALOG_KEYS)
|
|
865
914
|
return {
|
|
866
915
|
id: request,
|
|
867
916
|
type: 'close_file_dialog',
|
|
@@ -869,7 +918,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
869
918
|
dialog_id: id(message['dialog_id']),
|
|
870
919
|
}
|
|
871
920
|
case 'show_message_dialog':
|
|
872
|
-
keys(message,
|
|
921
|
+
keys(message, COMMAND_SHOW_MESSAGE_DIALOG_KEYS)
|
|
873
922
|
return {
|
|
874
923
|
id: request,
|
|
875
924
|
type: 'show_message_dialog',
|
|
@@ -878,7 +927,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
878
927
|
options: parseMessageDialogOptions(message['options']),
|
|
879
928
|
}
|
|
880
929
|
case 'close_message_dialog':
|
|
881
|
-
keys(message,
|
|
930
|
+
keys(message, COMMAND_CLOSE_MESSAGE_DIALOG_KEYS)
|
|
882
931
|
return {
|
|
883
932
|
id: request,
|
|
884
933
|
type: 'close_message_dialog',
|
|
@@ -886,7 +935,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
886
935
|
dialog_id: id(message['dialog_id']),
|
|
887
936
|
}
|
|
888
937
|
case 'show_context_menu':
|
|
889
|
-
keys(message,
|
|
938
|
+
keys(message, COMMAND_SHOW_CONTEXT_MENU_KEYS)
|
|
890
939
|
return {
|
|
891
940
|
id: request,
|
|
892
941
|
type: 'show_context_menu',
|
|
@@ -897,7 +946,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
897
946
|
items: parseContextMenuItems(message['items']),
|
|
898
947
|
}
|
|
899
948
|
case 'close_context_menu':
|
|
900
|
-
keys(message,
|
|
949
|
+
keys(message, COMMAND_CLOSE_CONTEXT_MENU_KEYS)
|
|
901
950
|
return {
|
|
902
951
|
id: request,
|
|
903
952
|
type: 'close_context_menu',
|
|
@@ -905,7 +954,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
905
954
|
menu_id: id(message['menu_id']),
|
|
906
955
|
}
|
|
907
956
|
case 'register_drop_target':
|
|
908
|
-
keys(message,
|
|
957
|
+
keys(message, COMMAND_REGISTER_DROP_TARGET_KEYS)
|
|
909
958
|
return {
|
|
910
959
|
id: request,
|
|
911
960
|
type: 'register_drop_target',
|
|
@@ -914,7 +963,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
914
963
|
node_id: id(message['node_id']),
|
|
915
964
|
}
|
|
916
965
|
case 'unregister_drop_target':
|
|
917
|
-
keys(message,
|
|
966
|
+
keys(message, COMMAND_UNREGISTER_DROP_TARGET_KEYS)
|
|
918
967
|
return {
|
|
919
968
|
id: request,
|
|
920
969
|
type: 'unregister_drop_target',
|
|
@@ -922,7 +971,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
922
971
|
target_id: id(message['target_id']),
|
|
923
972
|
}
|
|
924
973
|
case 'resolve_dropped_item':
|
|
925
|
-
keys(message,
|
|
974
|
+
keys(message, COMMAND_RESOLVE_DROPPED_ITEM_KEYS)
|
|
926
975
|
return {
|
|
927
976
|
id: request,
|
|
928
977
|
type: 'resolve_dropped_item',
|
|
@@ -933,7 +982,7 @@ export function parseCommand(value: unknown): Command {
|
|
|
933
982
|
root: parseRootId(message['root']),
|
|
934
983
|
}
|
|
935
984
|
case 'set_app_menu':
|
|
936
|
-
keys(message,
|
|
985
|
+
keys(message, COMMAND_SET_APP_MENU_KEYS)
|
|
937
986
|
return {
|
|
938
987
|
id: request,
|
|
939
988
|
type: 'set_app_menu',
|
|
@@ -941,16 +990,18 @@ export function parseCommand(value: unknown): Command {
|
|
|
941
990
|
menus: parseAppMenus(message['menus']),
|
|
942
991
|
}
|
|
943
992
|
case 'shutdown':
|
|
944
|
-
keys(message,
|
|
993
|
+
keys(message, COMMAND_SHUTDOWN_KEYS)
|
|
945
994
|
return { id: request, type: 'shutdown' }
|
|
946
995
|
default:
|
|
947
996
|
throw new ProtocolError('Unknown native command')
|
|
948
997
|
}
|
|
949
998
|
}
|
|
950
999
|
|
|
1000
|
+
const LIMITS_KEYS = fields(...Object.keys(DEFAULT_LIMITS))
|
|
1001
|
+
|
|
951
1002
|
function limits(value: unknown): Limits {
|
|
952
1003
|
const data = object(value)
|
|
953
|
-
keys(data,
|
|
1004
|
+
keys(data, LIMITS_KEYS)
|
|
954
1005
|
const parse = (key: keyof Limits) => integer(data[key], key, 1, DEFAULT_LIMITS[key])
|
|
955
1006
|
return {
|
|
956
1007
|
max_frame_bytes: parse('max_frame_bytes'),
|
|
@@ -974,13 +1025,21 @@ function limits(value: unknown): Limits {
|
|
|
974
1025
|
|
|
975
1026
|
const ROUTE_KEYS = ['type', 'sequence', 'window_id', 'node_id', 'tree_revision', 'path'] as const
|
|
976
1027
|
|
|
1028
|
+
/** Short paths, the common case, compare pairwise instead of building a set. */
|
|
1029
|
+
function unique(path: readonly number[]): boolean {
|
|
1030
|
+
if (path.length > 16) return new Set(path).size === path.length
|
|
1031
|
+
for (let index = 1; index < path.length; index++)
|
|
1032
|
+
for (let other = 0; other < index; other++) if (path[index] === path[other]) return false
|
|
1033
|
+
return true
|
|
1034
|
+
}
|
|
1035
|
+
|
|
977
1036
|
function route(message: Record<string, unknown>): NodeEventRoute {
|
|
978
1037
|
const node_id = id(message['node_id'])
|
|
979
1038
|
const value = message['path']
|
|
980
1039
|
if (!Array.isArray(value) || !value.length || value.length > MAX_DEPTH + 1)
|
|
981
1040
|
throw new ProtocolError('Native event path must contain between 1 and 65 node identities')
|
|
982
1041
|
const path = value.map(id)
|
|
983
|
-
if (
|
|
1042
|
+
if (!unique(path) || path.at(-1) !== node_id)
|
|
984
1043
|
throw new ProtocolError('Native event path must be unique and end at its target')
|
|
985
1044
|
return {
|
|
986
1045
|
sequence: id(message['sequence']),
|
|
@@ -991,9 +1050,11 @@ function route(message: Record<string, unknown>): NodeEventRoute {
|
|
|
991
1050
|
}
|
|
992
1051
|
}
|
|
993
1052
|
|
|
1053
|
+
const MODIFIERS_KEYS = fields('control', 'alt', 'shift', 'platform', 'function')
|
|
1054
|
+
|
|
994
1055
|
function modifiers(value: unknown): KeyModifiers {
|
|
995
1056
|
const data = object(value)
|
|
996
|
-
keys(data,
|
|
1057
|
+
keys(data, MODIFIERS_KEYS)
|
|
997
1058
|
const modifier = (name: keyof KeyModifiers) => {
|
|
998
1059
|
if (typeof data[name] !== 'boolean') throw new ProtocolError('Invalid native key modifier')
|
|
999
1060
|
return data[name]
|
|
@@ -1007,12 +1068,53 @@ function modifiers(value: unknown): KeyModifiers {
|
|
|
1007
1068
|
}
|
|
1008
1069
|
}
|
|
1009
1070
|
|
|
1071
|
+
const EVENT_READY_KEYS = fields('type', 'protocol', 'capabilities', 'limits', 'service_policy')
|
|
1072
|
+
const EVENT_ACK_KEYS = fields('type', 'id')
|
|
1073
|
+
const EVENT_OPENED_KEYS = windowReply('root_id', 'tree_revision')
|
|
1074
|
+
const EVENT_APPLIED_KEYS = windowReply('tree_revision')
|
|
1075
|
+
const EVENT_DISPLAY_SNAPSHOT_KEYS = windowReply('snapshot')
|
|
1076
|
+
const EVENT_CLIPBOARD_TEXT_KEYS = windowReply('result')
|
|
1077
|
+
const EVENT_CLIPBOARD_WRITTEN_KEYS = windowReply()
|
|
1078
|
+
const EVENT_GLOBAL_SHORTCUT_REGISTERED_KEYS = windowReply('shortcut_id')
|
|
1079
|
+
const EVENT_DISPLAY_CHANGED_KEYS = windowNotice('snapshot')
|
|
1080
|
+
const EVENT_GLOBAL_SHORTCUT_KEYS = windowNotice('shortcut_id')
|
|
1081
|
+
const EVENT_NOTIFICATION_POSTED_KEYS = windowReply('notification_id', 'activatable')
|
|
1082
|
+
const EVENT_NOTIFICATION_WITHDRAWN_KEYS = windowReply('notification_id')
|
|
1083
|
+
const EVENT_NOTIFICATION_ACTIVATED_KEYS = windowNotice('notification_id')
|
|
1084
|
+
const EVENT_NOTIFICATION_DISMISSED_KEYS = windowNotice('notification_id', 'reason')
|
|
1085
|
+
const EVENT_FILE_GRANT_OPENED_KEYS = windowReply('grant_id')
|
|
1086
|
+
const EVENT_FILE_RESULT_KEYS = windowReply('grant_id', 'result')
|
|
1087
|
+
const EVENT_PROCESS_SPAWNED_KEYS = windowReply('process_id')
|
|
1088
|
+
const EVENT_PROCESS_OUTPUT_KEYS = windowNotice('process_id', 'chunk', 'stream', 'data')
|
|
1089
|
+
const EVENT_PROCESS_EXITED_KEYS = windowNotice('process_id', 'exit')
|
|
1090
|
+
const EVENT_FILE_DIALOG_OPENED_KEYS = windowReply('dialog_id')
|
|
1091
|
+
const EVENT_FILE_DIALOG_COMPLETED_KEYS = windowNotice('dialog_id', 'result')
|
|
1092
|
+
const EVENT_MESSAGE_DIALOG_OPENED_KEYS = windowReply('dialog_id')
|
|
1093
|
+
const EVENT_MESSAGE_DIALOG_COMPLETED_KEYS = windowNotice('dialog_id', 'result')
|
|
1094
|
+
const EVENT_CONTEXT_MENU_OPENED_KEYS = windowReply('menu_id')
|
|
1095
|
+
const EVENT_CONTEXT_MENU_COMPLETED_KEYS = windowNotice('menu_id', 'item_id')
|
|
1096
|
+
const EVENT_DROP_TARGET_REGISTERED_KEYS = windowReply('target_id')
|
|
1097
|
+
const EVENT_DROPPED_ITEM_RESOLVED_KEYS = windowReply('target_id', 'drop_id', 'item', 'root', 'path')
|
|
1098
|
+
const EVENT_DROP_TARGET_DRAG_KEYS = windowNotice('target_id', 'state')
|
|
1099
|
+
const EVENT_DROP_RECEIVED_KEYS = windowNotice('target_id', 'drop_id', 'items')
|
|
1100
|
+
const EVENT_DROP_REJECTED_KEYS = windowNotice('target_id', 'reason')
|
|
1101
|
+
const EVENT_ROUTE_KEYS = fields(...ROUTE_KEYS)
|
|
1102
|
+
const EVENT_KEY_KEYS = fields(...ROUTE_KEYS, 'key', 'key_char', 'modifiers')
|
|
1103
|
+
const EVENT_POINTER_KEYS = fields(...ROUTE_KEYS, 'button', 'x', 'y', 'modifiers')
|
|
1104
|
+
const EVENT_DISMISS_KEYS = fields(...ROUTE_KEYS, 'reason')
|
|
1105
|
+
const EVENT_SPLIT_RESIZE_KEYS = fields(...ROUTE_KEYS, 'ratio', 'source')
|
|
1106
|
+
const EVENT_CLOSED_KEYS = windowNotice()
|
|
1107
|
+
const EVENT_INPUT_KEYS = fields(...ROUTE_KEYS, 'value', 'input_revision')
|
|
1108
|
+
const EVENT_APP_MENU_SET_KEYS = fields('type', 'id', 'menu_id')
|
|
1109
|
+
const EVENT_APP_MENU_ITEM_KEYS = fields('type', 'sequence', 'menu_id', 'item_id')
|
|
1110
|
+
const EVENT_ERROR_KEYS = fields('type', 'id', 'code', 'message')
|
|
1111
|
+
|
|
1010
1112
|
/** Native stdout is untrusted until its message shape and limits are checked. */
|
|
1011
1113
|
export function parseEvent(value: unknown): NativeEvent {
|
|
1012
1114
|
const message = object(value)
|
|
1013
1115
|
switch (message['type']) {
|
|
1014
1116
|
case 'ready': {
|
|
1015
|
-
keys(message,
|
|
1117
|
+
keys(message, EVENT_READY_KEYS)
|
|
1016
1118
|
const capabilities = message['capabilities']
|
|
1017
1119
|
if (!Array.isArray(capabilities) || capabilities.length > CAPABILITIES.length)
|
|
1018
1120
|
throw new ProtocolError('Invalid native capabilities')
|
|
@@ -1032,10 +1134,10 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1032
1134
|
}
|
|
1033
1135
|
}
|
|
1034
1136
|
case 'ack':
|
|
1035
|
-
keys(message,
|
|
1137
|
+
keys(message, EVENT_ACK_KEYS)
|
|
1036
1138
|
return { type: 'ack', id: id(message['id']) }
|
|
1037
1139
|
case 'opened':
|
|
1038
|
-
keys(message,
|
|
1140
|
+
keys(message, EVENT_OPENED_KEYS)
|
|
1039
1141
|
return {
|
|
1040
1142
|
type: 'opened',
|
|
1041
1143
|
id: id(message['id']),
|
|
@@ -1044,7 +1146,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1044
1146
|
tree_revision: integer(message['tree_revision'], 'tree revision'),
|
|
1045
1147
|
}
|
|
1046
1148
|
case 'applied':
|
|
1047
|
-
keys(message,
|
|
1149
|
+
keys(message, EVENT_APPLIED_KEYS)
|
|
1048
1150
|
return {
|
|
1049
1151
|
type: 'applied',
|
|
1050
1152
|
id: id(message['id']),
|
|
@@ -1052,7 +1154,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1052
1154
|
tree_revision: integer(message['tree_revision'], 'tree revision'),
|
|
1053
1155
|
}
|
|
1054
1156
|
case 'display_snapshot':
|
|
1055
|
-
keys(message,
|
|
1157
|
+
keys(message, EVENT_DISPLAY_SNAPSHOT_KEYS)
|
|
1056
1158
|
return {
|
|
1057
1159
|
type: 'display_snapshot',
|
|
1058
1160
|
id: id(message['id']),
|
|
@@ -1060,7 +1162,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1060
1162
|
snapshot: parseDisplaySnapshot(message['snapshot']),
|
|
1061
1163
|
}
|
|
1062
1164
|
case 'clipboard_text':
|
|
1063
|
-
keys(message,
|
|
1165
|
+
keys(message, EVENT_CLIPBOARD_TEXT_KEYS)
|
|
1064
1166
|
return {
|
|
1065
1167
|
type: 'clipboard_text',
|
|
1066
1168
|
id: id(message['id']),
|
|
@@ -1068,7 +1170,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1068
1170
|
result: parseClipboardText(message['result']),
|
|
1069
1171
|
}
|
|
1070
1172
|
case 'clipboard_written':
|
|
1071
|
-
keys(message,
|
|
1173
|
+
keys(message, EVENT_CLIPBOARD_WRITTEN_KEYS)
|
|
1072
1174
|
return {
|
|
1073
1175
|
type: 'clipboard_written',
|
|
1074
1176
|
id: id(message['id']),
|
|
@@ -1076,7 +1178,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1076
1178
|
}
|
|
1077
1179
|
case 'global_shortcut_registered':
|
|
1078
1180
|
case 'global_shortcut_unregistered':
|
|
1079
|
-
keys(message,
|
|
1181
|
+
keys(message, EVENT_GLOBAL_SHORTCUT_REGISTERED_KEYS)
|
|
1080
1182
|
return {
|
|
1081
1183
|
type: message['type'],
|
|
1082
1184
|
id: id(message['id']),
|
|
@@ -1084,7 +1186,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1084
1186
|
shortcut_id: id(message['shortcut_id']),
|
|
1085
1187
|
}
|
|
1086
1188
|
case 'display_changed':
|
|
1087
|
-
keys(message,
|
|
1189
|
+
keys(message, EVENT_DISPLAY_CHANGED_KEYS)
|
|
1088
1190
|
return {
|
|
1089
1191
|
type: 'display_changed',
|
|
1090
1192
|
sequence: id(message['sequence']),
|
|
@@ -1092,7 +1194,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1092
1194
|
snapshot: parseDisplaySnapshot(message['snapshot']),
|
|
1093
1195
|
}
|
|
1094
1196
|
case 'global_shortcut':
|
|
1095
|
-
keys(message,
|
|
1197
|
+
keys(message, EVENT_GLOBAL_SHORTCUT_KEYS)
|
|
1096
1198
|
return {
|
|
1097
1199
|
type: 'global_shortcut',
|
|
1098
1200
|
sequence: id(message['sequence']),
|
|
@@ -1100,7 +1202,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1100
1202
|
shortcut_id: id(message['shortcut_id']),
|
|
1101
1203
|
}
|
|
1102
1204
|
case 'notification_posted':
|
|
1103
|
-
keys(message,
|
|
1205
|
+
keys(message, EVENT_NOTIFICATION_POSTED_KEYS)
|
|
1104
1206
|
if (typeof message['activatable'] !== 'boolean')
|
|
1105
1207
|
throw new ProtocolError('Notification activatable must be a boolean')
|
|
1106
1208
|
return {
|
|
@@ -1111,7 +1213,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1111
1213
|
activatable: message['activatable'],
|
|
1112
1214
|
}
|
|
1113
1215
|
case 'notification_withdrawn':
|
|
1114
|
-
keys(message,
|
|
1216
|
+
keys(message, EVENT_NOTIFICATION_WITHDRAWN_KEYS)
|
|
1115
1217
|
return {
|
|
1116
1218
|
type: 'notification_withdrawn',
|
|
1117
1219
|
id: id(message['id']),
|
|
@@ -1119,7 +1221,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1119
1221
|
notification_id: id(message['notification_id']),
|
|
1120
1222
|
}
|
|
1121
1223
|
case 'notification_activated':
|
|
1122
|
-
keys(message,
|
|
1224
|
+
keys(message, EVENT_NOTIFICATION_ACTIVATED_KEYS)
|
|
1123
1225
|
return {
|
|
1124
1226
|
type: 'notification_activated',
|
|
1125
1227
|
sequence: id(message['sequence']),
|
|
@@ -1127,7 +1229,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1127
1229
|
notification_id: id(message['notification_id']),
|
|
1128
1230
|
}
|
|
1129
1231
|
case 'notification_dismissed':
|
|
1130
|
-
keys(message,
|
|
1232
|
+
keys(message, EVENT_NOTIFICATION_DISMISSED_KEYS)
|
|
1131
1233
|
return {
|
|
1132
1234
|
type: 'notification_dismissed',
|
|
1133
1235
|
sequence: id(message['sequence']),
|
|
@@ -1137,7 +1239,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1137
1239
|
}
|
|
1138
1240
|
case 'file_grant_opened':
|
|
1139
1241
|
case 'file_grant_closed':
|
|
1140
|
-
keys(message,
|
|
1242
|
+
keys(message, EVENT_FILE_GRANT_OPENED_KEYS)
|
|
1141
1243
|
return {
|
|
1142
1244
|
type: message['type'],
|
|
1143
1245
|
id: id(message['id']),
|
|
@@ -1145,7 +1247,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1145
1247
|
grant_id: id(message['grant_id']),
|
|
1146
1248
|
}
|
|
1147
1249
|
case 'file_result':
|
|
1148
|
-
keys(message,
|
|
1250
|
+
keys(message, EVENT_FILE_RESULT_KEYS)
|
|
1149
1251
|
return {
|
|
1150
1252
|
type: 'file_result',
|
|
1151
1253
|
id: id(message['id']),
|
|
@@ -1156,7 +1258,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1156
1258
|
case 'process_spawned':
|
|
1157
1259
|
case 'process_updated':
|
|
1158
1260
|
case 'process_released':
|
|
1159
|
-
keys(message,
|
|
1261
|
+
keys(message, EVENT_PROCESS_SPAWNED_KEYS)
|
|
1160
1262
|
return {
|
|
1161
1263
|
type: message['type'],
|
|
1162
1264
|
id: id(message['id']),
|
|
@@ -1164,7 +1266,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1164
1266
|
process_id: id(message['process_id']),
|
|
1165
1267
|
}
|
|
1166
1268
|
case 'process_output':
|
|
1167
|
-
keys(message,
|
|
1269
|
+
keys(message, EVENT_PROCESS_OUTPUT_KEYS)
|
|
1168
1270
|
return {
|
|
1169
1271
|
type: 'process_output',
|
|
1170
1272
|
sequence: id(message['sequence']),
|
|
@@ -1175,7 +1277,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1175
1277
|
data: parseProcessOutput(message['data']),
|
|
1176
1278
|
}
|
|
1177
1279
|
case 'process_exited':
|
|
1178
|
-
keys(message,
|
|
1280
|
+
keys(message, EVENT_PROCESS_EXITED_KEYS)
|
|
1179
1281
|
return {
|
|
1180
1282
|
type: 'process_exited',
|
|
1181
1283
|
sequence: id(message['sequence']),
|
|
@@ -1185,7 +1287,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1185
1287
|
}
|
|
1186
1288
|
case 'file_dialog_opened':
|
|
1187
1289
|
case 'file_dialog_closed':
|
|
1188
|
-
keys(message,
|
|
1290
|
+
keys(message, EVENT_FILE_DIALOG_OPENED_KEYS)
|
|
1189
1291
|
return {
|
|
1190
1292
|
type: message['type'],
|
|
1191
1293
|
id: id(message['id']),
|
|
@@ -1193,7 +1295,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1193
1295
|
dialog_id: id(message['dialog_id']),
|
|
1194
1296
|
}
|
|
1195
1297
|
case 'file_dialog_completed':
|
|
1196
|
-
keys(message,
|
|
1298
|
+
keys(message, EVENT_FILE_DIALOG_COMPLETED_KEYS)
|
|
1197
1299
|
return {
|
|
1198
1300
|
type: 'file_dialog_completed',
|
|
1199
1301
|
sequence: id(message['sequence']),
|
|
@@ -1203,7 +1305,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1203
1305
|
}
|
|
1204
1306
|
case 'message_dialog_opened':
|
|
1205
1307
|
case 'message_dialog_closed':
|
|
1206
|
-
keys(message,
|
|
1308
|
+
keys(message, EVENT_MESSAGE_DIALOG_OPENED_KEYS)
|
|
1207
1309
|
return {
|
|
1208
1310
|
type: message['type'],
|
|
1209
1311
|
id: id(message['id']),
|
|
@@ -1211,7 +1313,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1211
1313
|
dialog_id: id(message['dialog_id']),
|
|
1212
1314
|
}
|
|
1213
1315
|
case 'message_dialog_completed':
|
|
1214
|
-
keys(message,
|
|
1316
|
+
keys(message, EVENT_MESSAGE_DIALOG_COMPLETED_KEYS)
|
|
1215
1317
|
return {
|
|
1216
1318
|
type: 'message_dialog_completed',
|
|
1217
1319
|
sequence: id(message['sequence']),
|
|
@@ -1221,7 +1323,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1221
1323
|
}
|
|
1222
1324
|
case 'context_menu_opened':
|
|
1223
1325
|
case 'context_menu_closed':
|
|
1224
|
-
keys(message,
|
|
1326
|
+
keys(message, EVENT_CONTEXT_MENU_OPENED_KEYS)
|
|
1225
1327
|
return {
|
|
1226
1328
|
type: message['type'],
|
|
1227
1329
|
id: id(message['id']),
|
|
@@ -1229,7 +1331,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1229
1331
|
menu_id: id(message['menu_id']),
|
|
1230
1332
|
}
|
|
1231
1333
|
case 'context_menu_completed': {
|
|
1232
|
-
keys(message,
|
|
1334
|
+
keys(message, EVENT_CONTEXT_MENU_COMPLETED_KEYS)
|
|
1233
1335
|
const event: Extract<NativeEvent, { type: 'context_menu_completed' }> = {
|
|
1234
1336
|
type: 'context_menu_completed',
|
|
1235
1337
|
sequence: id(message['sequence']),
|
|
@@ -1241,7 +1343,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1241
1343
|
}
|
|
1242
1344
|
case 'drop_target_registered':
|
|
1243
1345
|
case 'drop_target_unregistered':
|
|
1244
|
-
keys(message,
|
|
1346
|
+
keys(message, EVENT_DROP_TARGET_REGISTERED_KEYS)
|
|
1245
1347
|
return {
|
|
1246
1348
|
type: message['type'],
|
|
1247
1349
|
id: id(message['id']),
|
|
@@ -1249,7 +1351,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1249
1351
|
target_id: id(message['target_id']),
|
|
1250
1352
|
}
|
|
1251
1353
|
case 'dropped_item_resolved':
|
|
1252
|
-
keys(message,
|
|
1354
|
+
keys(message, EVENT_DROPPED_ITEM_RESOLVED_KEYS)
|
|
1253
1355
|
return {
|
|
1254
1356
|
type: 'dropped_item_resolved',
|
|
1255
1357
|
id: id(message['id']),
|
|
@@ -1261,7 +1363,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1261
1363
|
path: parseFilePath(message['path']),
|
|
1262
1364
|
}
|
|
1263
1365
|
case 'drop_target_drag':
|
|
1264
|
-
keys(message,
|
|
1366
|
+
keys(message, EVENT_DROP_TARGET_DRAG_KEYS)
|
|
1265
1367
|
return {
|
|
1266
1368
|
type: 'drop_target_drag',
|
|
1267
1369
|
sequence: id(message['sequence']),
|
|
@@ -1270,7 +1372,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1270
1372
|
state: parseDragState(message['state']),
|
|
1271
1373
|
}
|
|
1272
1374
|
case 'drop_received':
|
|
1273
|
-
keys(message,
|
|
1375
|
+
keys(message, EVENT_DROP_RECEIVED_KEYS)
|
|
1274
1376
|
return {
|
|
1275
1377
|
type: 'drop_received',
|
|
1276
1378
|
sequence: id(message['sequence']),
|
|
@@ -1280,7 +1382,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1280
1382
|
items: parseDroppedItems(message['items']),
|
|
1281
1383
|
}
|
|
1282
1384
|
case 'drop_rejected':
|
|
1283
|
-
keys(message,
|
|
1385
|
+
keys(message, EVENT_DROP_REJECTED_KEYS)
|
|
1284
1386
|
return {
|
|
1285
1387
|
type: 'drop_rejected',
|
|
1286
1388
|
sequence: id(message['sequence']),
|
|
@@ -1291,14 +1393,14 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1291
1393
|
case 'click':
|
|
1292
1394
|
case 'focus':
|
|
1293
1395
|
case 'blur':
|
|
1294
|
-
keys(message,
|
|
1396
|
+
keys(message, EVENT_ROUTE_KEYS)
|
|
1295
1397
|
return {
|
|
1296
1398
|
type: message['type'],
|
|
1297
1399
|
...route(message),
|
|
1298
1400
|
}
|
|
1299
1401
|
case 'key_down':
|
|
1300
1402
|
case 'key_up': {
|
|
1301
|
-
keys(message,
|
|
1403
|
+
keys(message, EVENT_KEY_KEYS)
|
|
1302
1404
|
const key = string(message['key'], 'key', 256)
|
|
1303
1405
|
if (!key) throw new ProtocolError('Native key must be nonempty')
|
|
1304
1406
|
return {
|
|
@@ -1313,7 +1415,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1313
1415
|
}
|
|
1314
1416
|
case 'pointer_down':
|
|
1315
1417
|
case 'pointer_up': {
|
|
1316
|
-
keys(message,
|
|
1418
|
+
keys(message, EVENT_POINTER_KEYS)
|
|
1317
1419
|
const button = (['left', 'right', 'middle', 'back', 'forward'] as const).find(
|
|
1318
1420
|
(button) => button === message['button']
|
|
1319
1421
|
)
|
|
@@ -1328,12 +1430,12 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1328
1430
|
}
|
|
1329
1431
|
}
|
|
1330
1432
|
case 'dismiss':
|
|
1331
|
-
keys(message,
|
|
1433
|
+
keys(message, EVENT_DISMISS_KEYS)
|
|
1332
1434
|
if (message['reason'] !== 'window_blur')
|
|
1333
1435
|
throw new ProtocolError('Unknown native dismissal reason')
|
|
1334
1436
|
return { type: 'dismiss', ...route(message), reason: 'window_blur' }
|
|
1335
1437
|
case 'split_resize': {
|
|
1336
|
-
keys(message,
|
|
1438
|
+
keys(message, EVENT_SPLIT_RESIZE_KEYS)
|
|
1337
1439
|
const source = (['pointer', 'keyboard'] as const).find(
|
|
1338
1440
|
(source) => source === message['source']
|
|
1339
1441
|
)
|
|
@@ -1346,14 +1448,14 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1346
1448
|
}
|
|
1347
1449
|
}
|
|
1348
1450
|
case 'closed':
|
|
1349
|
-
keys(message,
|
|
1451
|
+
keys(message, EVENT_CLOSED_KEYS)
|
|
1350
1452
|
return {
|
|
1351
1453
|
type: 'closed',
|
|
1352
1454
|
sequence: id(message['sequence']),
|
|
1353
1455
|
window_id: id(message['window_id']),
|
|
1354
1456
|
}
|
|
1355
1457
|
case 'input':
|
|
1356
|
-
keys(message,
|
|
1458
|
+
keys(message, EVENT_INPUT_KEYS)
|
|
1357
1459
|
return {
|
|
1358
1460
|
type: 'input',
|
|
1359
1461
|
...route(message),
|
|
@@ -1361,10 +1463,10 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1361
1463
|
input_revision: integer(message['input_revision'], 'input revision'),
|
|
1362
1464
|
}
|
|
1363
1465
|
case 'app_menu_set':
|
|
1364
|
-
keys(message,
|
|
1466
|
+
keys(message, EVENT_APP_MENU_SET_KEYS)
|
|
1365
1467
|
return { type: 'app_menu_set', id: id(message['id']), menu_id: id(message['menu_id']) }
|
|
1366
1468
|
case 'app_menu_item':
|
|
1367
|
-
keys(message,
|
|
1469
|
+
keys(message, EVENT_APP_MENU_ITEM_KEYS)
|
|
1368
1470
|
return {
|
|
1369
1471
|
type: 'app_menu_item',
|
|
1370
1472
|
sequence: id(message['sequence']),
|
|
@@ -1372,7 +1474,7 @@ export function parseEvent(value: unknown): NativeEvent {
|
|
|
1372
1474
|
item_id: parseAppMenuItemId(message['item_id']),
|
|
1373
1475
|
}
|
|
1374
1476
|
case 'error': {
|
|
1375
|
-
keys(message,
|
|
1477
|
+
keys(message, EVENT_ERROR_KEYS)
|
|
1376
1478
|
const code = ERROR_CODES.find((code) => code === message['code'])
|
|
1377
1479
|
if (!code) throw new ProtocolError('Invalid native error code')
|
|
1378
1480
|
return {
|