diff options
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 |
