diff options
author | Christoph Lohmann <20h@r-36.net> | 2015-03-14 07:41:59 +0100 |
---|---|---|
committer | Christoph Lohmann <20h@r-36.net> | 2015-03-14 07:41:59 +0100 |
commit | 2fcfea1bf149f839cdbcba5c1efc7c4ce31f6d95 (patch) | |
tree | 704a13968ea68156f0f9b1196bad341d175dabfe | |
parent | b746816b78447b9e4a3af7333a4e992eb8d32254 (diff) | |
download | st-2fcfea1bf149f839cdbcba5c1efc7c4ce31f6d95.tar.gz st-2fcfea1bf149f839cdbcba5c1efc7c4ce31f6d95.zip |
Add Mod + Shift + c/v and no selclear.
Thanks to Alex Pilon <alp@alexpilon.ca>!
Now there is a distinction between the primary and clipboard selection. With
Mod + Shift + c/v the clipboard is handled. The old Insert behavious does
reside.
-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 | ||