diff options
| -rw-r--r-- | config.def.h | 2 | ||||
| -rw-r--r-- | st.c | 69 |
2 files changed, 56 insertions, 15 deletions
diff --git a/config.def.h b/config.def.h index 8a8236c..56bae2d 100644 --- a/config.def.h +++ b/config.def.h | |||
| @@ -119,6 +119,8 @@ static Shortcut shortcuts[] = { | |||
| 119 | { MODKEY|ShiftMask, XK_Home, xzoomreset, {.i = 0} }, | 119 | { MODKEY|ShiftMask, XK_Home, xzoomreset, {.i = 0} }, |
| 120 | { ShiftMask, XK_Insert, selpaste, {.i = 0} }, | 120 | { ShiftMask, XK_Insert, selpaste, {.i = 0} }, |
| 121 | { MODKEY|ShiftMask, XK_Insert, clippaste, {.i = 0} }, | 121 | { MODKEY|ShiftMask, XK_Insert, clippaste, {.i = 0} }, |
| 122 | { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} }, | ||
| 123 | { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} }, | ||
| 122 | { MODKEY, XK_Num_Lock, numlock, {.i = 0} }, | 124 | { MODKEY, XK_Num_Lock, numlock, {.i = 0} }, |
| 123 | }; | 125 | }; |
| 124 | 126 | ||
| @@ -290,7 +290,7 @@ typedef struct { | |||
| 290 | int x, y; | 290 | int x, y; |
| 291 | } nb, ne, ob, oe; | 291 | } nb, ne, ob, oe; |
| 292 | 292 | ||
| 293 | char *clip; | 293 | char *primary, *clipboard; |
| 294 | Atom xtarget; | 294 | Atom xtarget; |
| 295 | bool alt; | 295 | bool alt; |
| 296 | struct timespec tclick1; | 296 | struct timespec tclick1; |
| @@ -312,6 +312,7 @@ typedef struct { | |||
| 312 | } Shortcut; | 312 | } Shortcut; |
| 313 | 313 | ||
| 314 | /* function definitions used in config.h */ | 314 | /* function definitions used in config.h */ |
| 315 | static void clipcopy(const Arg *); | ||
| 315 | static void clippaste(const Arg *); | 316 | static void clippaste(const Arg *); |
| 316 | static void numlock(const Arg *); | 317 | static void numlock(const Arg *); |
| 317 | static void selpaste(const Arg *); | 318 | static void selpaste(const Arg *); |
| @@ -479,7 +480,11 @@ static void (*handler[LASTEvent])(XEvent *) = { | |||
| 479 | [MotionNotify] = bmotion, | 480 | [MotionNotify] = bmotion, |
| 480 | [ButtonPress] = bpress, | 481 | [ButtonPress] = bpress, |
| 481 | [ButtonRelease] = brelease, | 482 | [ButtonRelease] = brelease, |
| 482 | [SelectionClear] = selclear, | 483 | /* |
| 484 | * Uncomment if you want the selection to disappear when you select something | ||
| 485 | * different in another window. | ||
| 486 | */ | ||
| 487 | /* [SelectionClear] = selclear, */ | ||
| 483 | [SelectionNotify] = selnotify, | 488 | [SelectionNotify] = selnotify, |
| 484 | [SelectionRequest] = selrequest, | 489 | [SelectionRequest] = selrequest, |
| 485 | }; | 490 | }; |
| @@ -640,7 +645,8 @@ selinit(void) { | |||
| 640 | memset(&sel.tclick2, 0, sizeof(sel.tclick2)); | 645 | memset(&sel.tclick2, 0, sizeof(sel.tclick2)); |
| 641 | sel.mode = 0; | 646 | sel.mode = 0; |
| 642 | sel.ob.x = -1; | 647 | sel.ob.x = -1; |
| 643 | sel.clip = NULL; | 648 | sel.primary = NULL; |
| 649 | sel.clipboard = NULL; | ||
| 644 | sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); | 650 | sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); |
| 645 | if(sel.xtarget == None) | 651 | if(sel.xtarget == None) |
| 646 | sel.xtarget = XA_STRING; | 652 | sel.xtarget = XA_STRING; |
| @@ -985,12 +991,15 @@ selnotify(XEvent *e) { | |||
| 985 | int format; | 991 | int format; |
| 986 | uchar *data, *last, *repl; | 992 | uchar *data, *last, *repl; |
| 987 | Atom type; | 993 | Atom type; |
| 994 | XSelectionEvent *xsev; | ||
| 988 | 995 | ||
| 989 | ofs = 0; | 996 | ofs = 0; |
| 997 | xsev = (XSelectionEvent *)e; | ||
| 990 | do { | 998 | do { |
| 991 | if(XGetWindowProperty(xw.dpy, xw.win, XA_PRIMARY, ofs, BUFSIZ/4, | 999 | if(XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs, |
| 992 | False, AnyPropertyType, &type, &format, | 1000 | BUFSIZ/4, False, AnyPropertyType, |
| 993 | &nitems, &rem, &data)) { | 1001 | &type, &format, &nitems, &rem, |
| 1002 | &data)) { | ||
| 994 | fprintf(stderr, "Clipboard allocation failed\n"); | 1003 | fprintf(stderr, "Clipboard allocation failed\n"); |
| 995 | return; | 1004 | return; |
| 996 | } | 1005 | } |
| @@ -1026,11 +1035,25 @@ selpaste(const Arg *dummy) { | |||
| 1026 | } | 1035 | } |
| 1027 | 1036 | ||
| 1028 | void | 1037 | void |
| 1038 | clipcopy(const Arg *dummy) { | ||
| 1039 | Atom clipboard; | ||
| 1040 | |||
| 1041 | if(sel.clipboard != NULL) | ||
| 1042 | free(sel.clipboard); | ||
| 1043 | |||
| 1044 | if(sel.primary != NULL) { | ||
| 1045 | sel.clipboard = xstrdup(sel.primary); | ||
| 1046 | clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); | ||
| 1047 | XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); | ||
| 1048 | } | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | void | ||
| 1029 | clippaste(const Arg *dummy) { | 1052 | clippaste(const Arg *dummy) { |
| 1030 | Atom clipboard; | 1053 | Atom clipboard; |
| 1031 | 1054 | ||
| 1032 | clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); | 1055 | clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); |
| 1033 | XConvertSelection(xw.dpy, clipboard, sel.xtarget, XA_PRIMARY, | 1056 | XConvertSelection(xw.dpy, clipboard, sel.xtarget, clipboard, |
| 1034 | xw.win, CurrentTime); | 1057 | xw.win, CurrentTime); |
| 1035 | } | 1058 | } |
| 1036 | 1059 | ||
| @@ -1046,7 +1069,8 @@ void | |||
| 1046 | selrequest(XEvent *e) { | 1069 | selrequest(XEvent *e) { |
| 1047 | XSelectionRequestEvent *xsre; | 1070 | XSelectionRequestEvent *xsre; |
| 1048 | XSelectionEvent xev; | 1071 | XSelectionEvent xev; |
| 1049 | Atom xa_targets, string; | 1072 | Atom xa_targets, string, clipboard; |
| 1073 | char *seltext; | ||
| 1050 | 1074 | ||
| 1051 | xsre = (XSelectionRequestEvent *) e; | 1075 | xsre = (XSelectionRequestEvent *) e; |
| 1052 | xev.type = SelectionNotify; | 1076 | xev.type = SelectionNotify; |
| @@ -1065,11 +1089,25 @@ selrequest(XEvent *e) { | |||
| 1065 | XA_ATOM, 32, PropModeReplace, | 1089 | XA_ATOM, 32, PropModeReplace, |
| 1066 | (uchar *) &string, 1); | 1090 | (uchar *) &string, 1); |
| 1067 | xev.property = xsre->property; | 1091 | xev.property = xsre->property; |
| 1068 | } else if(xsre->target == sel.xtarget && sel.clip != NULL) { | 1092 | } else if(xsre->target == sel.xtarget) { |
| 1069 | XChangeProperty(xsre->display, xsre->requestor, xsre->property, | 1093 | clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); |
| 1070 | xsre->target, 8, PropModeReplace, | 1094 | if(xsre->selection == XA_PRIMARY) { |
| 1071 | (uchar *) sel.clip, strlen(sel.clip)); | 1095 | seltext = sel.primary; |
| 1072 | xev.property = xsre->property; | 1096 | } else if(xsre->selection == clipboard) { |
| 1097 | seltext = sel.clipboard; | ||
| 1098 | } else { | ||
| 1099 | fprintf(stderr, | ||
| 1100 | "Unhandled clipboard selection 0x%lx\n", | ||
| 1101 | xsre->selection); | ||
| 1102 | return; | ||
| 1103 | } | ||
| 1104 | if(seltext != NULL) { | ||
| 1105 | XChangeProperty(xsre->display, xsre->requestor, | ||
| 1106 | xsre->property, xsre->target, | ||
| 1107 | 8, PropModeReplace, | ||
| 1108 | (uchar *)seltext, strlen(seltext)); | ||
| 1109 | xev.property = xsre->property; | ||
| 1110 | } | ||
| 1073 | } | 1111 | } |
| 1074 | 1112 | ||
| 1075 | /* all done, send a notification to the listener */ | 1113 | /* all done, send a notification to the listener */ |
| @@ -1079,8 +1117,9 @@ selrequest(XEvent *e) { | |||
| 1079 | 1117 | ||
| 1080 | void | 1118 | void |
| 1081 | xsetsel(char *str) { | 1119 | xsetsel(char *str) { |
| 1082 | free(sel.clip); | 1120 | free(sel.primary); |
| 1083 | sel.clip = str; | 1121 | sel.primary = str; |
| 1122 | |||
| 1084 | XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, CurrentTime); | 1123 | XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, CurrentTime); |
| 1085 | } | 1124 | } |
| 1086 | 1125 | ||
