diff options
Diffstat (limited to '')
| -rw-r--r-- | st.c | 130 |
1 files changed, 124 insertions, 6 deletions
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <sys/wait.h> | 17 | #include <sys/wait.h> |
| 18 | #include <unistd.h> | 18 | #include <unistd.h> |
| 19 | #include <X11/Xlib.h> | 19 | #include <X11/Xlib.h> |
| 20 | #include <X11/Xatom.h> | ||
| 20 | #include <X11/keysym.h> | 21 | #include <X11/keysym.h> |
| 21 | #include <X11/Xutil.h> | 22 | #include <X11/Xutil.h> |
| 22 | 23 | ||
| @@ -199,7 +200,8 @@ static void focus(XEvent *); | |||
| 199 | static void brelease(XEvent *); | 200 | static void brelease(XEvent *); |
| 200 | static void bpress(XEvent *); | 201 | static void bpress(XEvent *); |
| 201 | static void bmotion(XEvent *); | 202 | static void bmotion(XEvent *); |
| 202 | 203 | static void selection_notify(XEvent *); | |
| 204 | static void selection_request(XEvent *); | ||
| 203 | 205 | ||
| 204 | static void (*handler[LASTEvent])(XEvent *) = { | 206 | static void (*handler[LASTEvent])(XEvent *) = { |
| 205 | [KeyPress] = kpress, | 207 | [KeyPress] = kpress, |
| @@ -212,6 +214,8 @@ static void (*handler[LASTEvent])(XEvent *) = { | |||
| 212 | [MotionNotify] = bmotion, | 214 | [MotionNotify] = bmotion, |
| 213 | [ButtonPress] = bpress, | 215 | [ButtonPress] = bpress, |
| 214 | [ButtonRelease] = brelease, | 216 | [ButtonRelease] = brelease, |
| 217 | [SelectionNotify] = selection_notify, | ||
| 218 | [SelectionRequest] = selection_request, | ||
| 215 | }; | 219 | }; |
| 216 | 220 | ||
| 217 | /* Globals */ | 221 | /* Globals */ |
| @@ -278,15 +282,129 @@ static char *getseltext() { | |||
| 278 | return str; | 282 | return str; |
| 279 | } | 283 | } |
| 280 | 284 | ||
| 281 | /* TODO: use X11 clipboard */ | 285 | static void selection_notify(XEvent *e) { |
| 286 | unsigned long nitems; | ||
| 287 | unsigned long length; | ||
| 288 | int format, res; | ||
| 289 | unsigned char *data; | ||
| 290 | Atom type; | ||
| 291 | |||
| 292 | res = XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, 0, 0, False, | ||
| 293 | AnyPropertyType, &type, &format, &nitems, &length, &data); | ||
| 294 | switch(res) { | ||
| 295 | case BadAtom: | ||
| 296 | case BadValue: | ||
| 297 | case BadWindow: | ||
| 298 | fprintf(stderr, "Invalid paste, XGetWindowProperty0"); | ||
| 299 | return; | ||
| 300 | } | ||
| 301 | |||
| 302 | res = XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, 0, length, False, | ||
| 303 | AnyPropertyType, &type, &format, &nitems, &length, &data); | ||
| 304 | switch(res) { | ||
| 305 | case BadAtom: | ||
| 306 | case BadValue: | ||
| 307 | case BadWindow: | ||
| 308 | fprintf(stderr, "Invalid paste, XGetWindowProperty0"); | ||
| 309 | return; | ||
| 310 | } | ||
| 311 | |||
| 312 | if(data) { | ||
| 313 | ttywrite((const char *) data, nitems * format / 8); | ||
| 314 | XFree(data); | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | static void selpaste() { | ||
| 319 | XConvertSelection(xw.dis, XA_PRIMARY, XA_STRING, XA_PRIMARY, xw.win, CurrentTime); | ||
| 320 | } | ||
| 321 | |||
| 322 | static void selection_request(XEvent *e) | ||
| 323 | { | ||
| 324 | XSelectionRequestEvent *xsre; | ||
| 325 | XSelectionEvent xev; | ||
| 326 | int res; | ||
| 327 | Atom xa_targets; | ||
| 328 | |||
| 329 | xsre = (XSelectionRequestEvent *) e; | ||
| 330 | xev.type = SelectionNotify; | ||
| 331 | xev.requestor = xsre->requestor; | ||
| 332 | xev.selection = xsre->selection; | ||
| 333 | xev.target = xsre->target; | ||
| 334 | xev.time = xsre->time; | ||
| 335 | /* reject */ | ||
| 336 | xev.property = None; | ||
| 337 | |||
| 338 | xa_targets = XInternAtom(xw.dis, "TARGETS", 0); | ||
| 339 | if(xsre->target == xa_targets) { | ||
| 340 | /* respond with the supported type */ | ||
| 341 | Atom string = XA_STRING; | ||
| 342 | res = XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, | ||
| 343 | PropModeReplace, (unsigned char *) &string, 1); | ||
| 344 | switch(res) { | ||
| 345 | case BadAlloc: | ||
| 346 | case BadAtom: | ||
| 347 | case BadMatch: | ||
| 348 | case BadValue: | ||
| 349 | case BadWindow: | ||
| 350 | fprintf(stderr, "Error in selection_request, TARGETS"); | ||
| 351 | break; | ||
| 352 | default: | ||
| 353 | xev.property = xsre->property; | ||
| 354 | } | ||
| 355 | } else if(xsre->target == XA_STRING) { | ||
| 356 | res = XChangeProperty(xsre->display, xsre->requestor, xsre->property, | ||
| 357 | xsre->target, 8, PropModeReplace, (unsigned char *) sel.clip, | ||
| 358 | strlen(sel.clip)); | ||
| 359 | switch(res) { | ||
| 360 | case BadAlloc: | ||
| 361 | case BadAtom: | ||
| 362 | case BadMatch: | ||
| 363 | case BadValue: | ||
| 364 | case BadWindow: | ||
| 365 | fprintf(stderr, "Error in selection_request, XA_STRING"); | ||
| 366 | break; | ||
| 367 | default: | ||
| 368 | xev.property = xsre->property; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | /* all done, send a notification to the listener */ | ||
| 373 | res = XSendEvent(xsre->display, xsre->requestor, True, 0, (XEvent *) &xev); | ||
| 374 | switch(res) { | ||
| 375 | case 0: | ||
| 376 | case BadValue: | ||
| 377 | case BadWindow: | ||
| 378 | fprintf(stderr, "Error in selection_requested, XSendEvent"); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 282 | static void selcopy(char *str) { | 382 | static void selcopy(char *str) { |
| 383 | /* register the selection for both the clipboard and the primary */ | ||
| 384 | Atom clipboard; | ||
| 385 | int res; | ||
| 386 | |||
| 283 | free(sel.clip); | 387 | free(sel.clip); |
| 284 | sel.clip = str; | 388 | sel.clip = str; |
| 285 | } | ||
| 286 | 389 | ||
| 287 | static void selpaste() { | 390 | res = XSetSelectionOwner(xw.dis, XA_PRIMARY, xw.win, CurrentTime); |
| 288 | if(sel.clip) | 391 | switch(res) { |
| 289 | ttywrite(sel.clip, strlen(sel.clip)); | 392 | case BadAtom: |
| 393 | case BadWindow: | ||
| 394 | fprintf(stderr, "Invalid copy, XSetSelectionOwner"); | ||
| 395 | return; | ||
| 396 | } | ||
| 397 | |||
| 398 | clipboard = XInternAtom(xw.dis, "CLIPBOARD", 0); | ||
| 399 | res = XSetSelectionOwner(xw.dis, clipboard, xw.win, CurrentTime); | ||
| 400 | switch(res) { | ||
| 401 | case BadAtom: | ||
| 402 | case BadWindow: | ||
| 403 | fprintf(stderr, "Invalid copy, XSetSelectionOwner"); | ||
| 404 | return; | ||
| 405 | } | ||
| 406 | |||
| 407 | XFlush(xw.dis); | ||
| 290 | } | 408 | } |
| 291 | 409 | ||
| 292 | /* TODO: doubleclick to select word */ | 410 | /* TODO: doubleclick to select word */ |
