diff options
author | Christoph Lohmann <20h@r-36.net> | 2015-07-10 14:10:17 +0200 |
---|---|---|
committer | Christoph Lohmann <20h@r-36.net> | 2015-07-10 14:10:17 +0200 |
commit | f8c6e7d0419d10c1425cb2c7123c5798ffb3b942 (patch) | |
tree | 659acb41481f2c8f7e7575ecbfd174312b3efbcb /st.c | |
parent | 539afe3af1b0d8b56b9ebfaa3bb7fc4e40f68c71 (diff) | |
download | st-f8c6e7d0419d10c1425cb2c7123c5798ffb3b942.tar.gz st-f8c6e7d0419d10c1425cb2c7123c5798ffb3b942.zip |
Implement INCR transfers in the clipboard.
Diffstat (limited to 'st.c')
-rw-r--r-- | st.c | 74 |
1 files changed, 68 insertions, 6 deletions
@@ -452,6 +452,7 @@ static void focus(XEvent *); | |||
452 | static void brelease(XEvent *); | 452 | static void brelease(XEvent *); |
453 | static void bpress(XEvent *); | 453 | static void bpress(XEvent *); |
454 | static void bmotion(XEvent *); | 454 | static void bmotion(XEvent *); |
455 | static void propnotify(XEvent *); | ||
455 | static void selnotify(XEvent *); | 456 | static void selnotify(XEvent *); |
456 | static void selclear(XEvent *); | 457 | static void selclear(XEvent *); |
457 | static void selrequest(XEvent *); | 458 | static void selrequest(XEvent *); |
@@ -500,6 +501,11 @@ static void (*handler[LASTEvent])(XEvent *) = { | |||
500 | */ | 501 | */ |
501 | /* [SelectionClear] = selclear, */ | 502 | /* [SelectionClear] = selclear, */ |
502 | [SelectionNotify] = selnotify, | 503 | [SelectionNotify] = selnotify, |
504 | /* | ||
505 | * PropertyNotify is only turned on when there is some INCR transfer happening | ||
506 | * for the selection retrieval. | ||
507 | */ | ||
508 | [PropertyNotify] = propnotify, | ||
503 | [SelectionRequest] = selrequest, | 509 | [SelectionRequest] = selrequest, |
504 | }; | 510 | }; |
505 | 511 | ||
@@ -1029,20 +1035,40 @@ selcopy(Time t) | |||
1029 | } | 1035 | } |
1030 | 1036 | ||
1031 | void | 1037 | void |
1038 | propnotify(XEvent *e) | ||
1039 | { | ||
1040 | XPropertyEvent *xpev; | ||
1041 | Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); | ||
1042 | |||
1043 | xpev = &e->xproperty; | ||
1044 | if (xpev->state == PropertyNewValue && | ||
1045 | (xpev->atom == XA_PRIMARY || | ||
1046 | xpev->atom == clipboard)) { | ||
1047 | slenotify(e); | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | void | ||
1032 | selnotify(XEvent *e) | 1052 | selnotify(XEvent *e) |
1033 | { | 1053 | { |
1034 | ulong nitems, ofs, rem; | 1054 | ulong nitems, ofs, rem; |
1035 | int format; | 1055 | int format; |
1036 | uchar *data, *last, *repl; | 1056 | uchar *data, *last, *repl; |
1037 | Atom type; | 1057 | Atom type, incratom, property; |
1038 | XSelectionEvent *xsev; | ||
1039 | 1058 | ||
1040 | ofs = 0; | 1059 | ofs = 0; |
1041 | xsev = &e->xselection; | 1060 | if (e->type == SelectionNotify) { |
1042 | if (xsev->property == None) | 1061 | property = e->xselection.property; |
1043 | return; | 1062 | } else if(e->type == PropertyNotify) { |
1063 | property = e->xproperty.atom; | ||
1064 | } else { | ||
1065 | return; | ||
1066 | } | ||
1067 | if (property == None) | ||
1068 | return; | ||
1069 | |||
1044 | do { | 1070 | do { |
1045 | if (XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs, | 1071 | if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, |
1046 | BUFSIZ/4, False, AnyPropertyType, | 1072 | BUFSIZ/4, False, AnyPropertyType, |
1047 | &type, &format, &nitems, &rem, | 1073 | &type, &format, &nitems, &rem, |
1048 | &data)) { | 1074 | &data)) { |
@@ -1050,6 +1076,35 @@ selnotify(XEvent *e) | |||
1050 | return; | 1076 | return; |
1051 | } | 1077 | } |
1052 | 1078 | ||
1079 | if (e->type == PropertyNotify && nitems == 0 && rem == 0) { | ||
1080 | /* | ||
1081 | * If there is some PropertyNotify with no data, then | ||
1082 | * this is the signal of the selection owner that all | ||
1083 | * data has been transferred. We won't need to receive | ||
1084 | * PropertyNotify events anymore. | ||
1085 | */ | ||
1086 | MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); | ||
1087 | XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, | ||
1088 | &xw.attrs); | ||
1089 | } | ||
1090 | |||
1091 | if (type == incratom) { | ||
1092 | /* | ||
1093 | * Activate the PropertyNotify events so we receive | ||
1094 | * when the selection owner does send us the next | ||
1095 | * chunk of data. | ||
1096 | */ | ||
1097 | MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); | ||
1098 | XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, | ||
1099 | &xw.attrs); | ||
1100 | |||
1101 | /* | ||
1102 | * Deleting the property is the transfer start signal. | ||
1103 | */ | ||
1104 | XDeleteProperty(xw.dpy, xw.win, (int)property); | ||
1105 | continue; | ||
1106 | } | ||
1107 | |||
1053 | /* | 1108 | /* |
1054 | * As seen in getsel: | 1109 | * As seen in getsel: |
1055 | * Line endings are inconsistent in the terminal and GUI world | 1110 | * Line endings are inconsistent in the terminal and GUI world |
@@ -1072,6 +1127,13 @@ selnotify(XEvent *e) | |||
1072 | /* number of 32-bit chunks returned */ | 1127 | /* number of 32-bit chunks returned */ |
1073 | ofs += nitems * format / 32; | 1128 | ofs += nitems * format / 32; |
1074 | } while (rem > 0); | 1129 | } while (rem > 0); |
1130 | |||
1131 | /* | ||
1132 | * Deleting the property again tells the selection owner to send the | ||
1133 | * next data chunk in the property. | ||
1134 | */ | ||
1135 | if (e->type == PropertyNotify) | ||
1136 | XDeleteProperty(xw.dpy, xw.win, (int)property); | ||
1075 | } | 1137 | } |
1076 | 1138 | ||
1077 | void | 1139 | void |