@@ -976,7 +976,7 @@ static Time get_clipboard_xevent_timestamp(bool logging) {
976976
977977/* fetch clippboard content from file */
978978/* lock already taken in is_special_keypress() */
979- static void get_qubes_clipboard (Ghandles * g , char * * data , int * len )
979+ static void get_qubes_clipboard (Ghandles * g , char * * data , int * len , bool multipaste )
980980{
981981 FILE * file ;
982982 * len = 0 ;
@@ -1041,7 +1041,16 @@ static void get_qubes_clipboard(Ghandles *g, char **data, int *len)
10411041 fclose (file );
10421042 metadata .sent_size = * len ;
10431043 metadata .successful = true;
1044- clear_clipboard (& metadata );
1044+ if (multipaste ) {
1045+ // triggering notification by updating file modification time
1046+ if (utimensat (0 , QUBES_CLIPBOARD_FILENAME , NULL , 0 ) == -1 ) {
1047+ show_error_message (g , "secure multi-paste: failed to update modification time of file " QUBES_CLIPBOARD_FILENAME );
1048+ } else {
1049+ metadata .cleared = false;
1050+ save_clipboard_metadata (& metadata );
1051+ }
1052+ } else
1053+ clear_clipboard (& metadata );
10451054}
10461055
10471056/* This is specific to Microsoft Windows and non-X11 compliant OS */
@@ -1513,8 +1522,13 @@ static int is_special_keypress(Ghandles * g, const XKeyEvent * ev, XID remote_wi
15131522 }
15141523
15151524 /* paste */
1516- if (((int )ev -> state & SPECIAL_KEYS_MASK ) == g -> paste_seq_mask
1517- && ev -> keycode == XKeysymToKeycode (g -> display , g -> paste_seq_key )) {
1525+ bool multipaste = false;
1526+ if (((int )ev -> state & SPECIAL_KEYS_MASK ) == g -> multipaste_seq_mask
1527+ && ev -> keycode == XKeysymToKeycode (g -> display , g -> multipaste_seq_key )) {
1528+ multipaste = true;
1529+ }
1530+ if (multipaste || (((int )ev -> state & SPECIAL_KEYS_MASK ) == g -> paste_seq_mask
1531+ && ev -> keycode == XKeysymToKeycode (g -> display , g -> paste_seq_key ))) {
15181532 if (ev -> type != KeyPress )
15191533 return 1 ;
15201534 inter_appviewer_lock (g , 1 );
@@ -1541,7 +1555,7 @@ static int is_special_keypress(Ghandles * g, const XKeyEvent * ev, XID remote_wi
15411555 hdr .type = MSG_CLIPBOARD_DATA ;
15421556 if (g -> log_level > 0 )
15431557 fprintf (stderr , "secure paste\n" );
1544- get_qubes_clipboard (g , & data , & len );
1558+ get_qubes_clipboard (g , & data , & len , multipaste );
15451559 if (len > 0 ) {
15461560 /* MSG_CLIPBOARD_DATA used to use the window field to pass the length
15471561 of the blob, be aware when working with old implementations. */
@@ -4345,6 +4359,8 @@ static void load_default_config_values(Ghandles * g)
43454359 g -> copy_seq_key = XK_c ;
43464360 g -> paste_seq_mask = ControlMask | ShiftMask ;
43474361 g -> paste_seq_key = XK_v ;
4362+ g -> multipaste_seq_mask = 0 ;
4363+ g -> multipaste_seq_key = NoSymbol ;
43484364 g -> clipboard_buffer_size = DEFAULT_CLIPBOARD_BUFFER_SIZE ;
43494365 g -> allow_fullscreen = 0 ;
43504366 g -> override_redirect_protection = 1 ;
@@ -4416,6 +4432,11 @@ static void parse_vm_config(Ghandles * g, config_setting_t * group)
44164432 parse_key_sequence (config_setting_get_string (setting ),
44174433 & g -> paste_seq_mask , & g -> paste_seq_key );
44184434 }
4435+ if ((setting =
4436+ config_setting_get_member (group , "secure_multipaste_sequence" ))) {
4437+ parse_key_sequence (config_setting_get_string (setting ),
4438+ & g -> multipaste_seq_mask , & g -> multipaste_seq_key );
4439+ }
44194440
44204441 if ((setting =
44214442 config_setting_get_member (group , "max_clipboard_size" ))) {
0 commit comments