Compare commits

..

No commits in common. "bf723703370cd4452def0809a42a6b11439eb2df" and "8f8e68a83b6475886d4fee96a1139b9d765e4a5f" have entirely different histories.

4 changed files with 30 additions and 142 deletions

View File

@ -16,10 +16,8 @@
CC=gcc CC=gcc
DEBUG=0 DEBUG=0
PREFIX=/usr/local
INCFLAGS=`pkg-config x11 --cflags` INCFLAGS=`pkg-config x11 --cflags`
LDFLAGS=`pkg-config x11 --libs` LDFLAGS=`pkg-config x11 --libs`
DEFS=-DVERSION=\"1.0\"
CFLAGS=$(INCFLAGS) -std=c99 -Wall -Wextra -Wfatal-errors -Werror CFLAGS=$(INCFLAGS) -std=c99 -Wall -Wextra -Wfatal-errors -Werror
HDRS= HDRS=
OBJS=src/main.o OBJS=src/main.o
@ -36,13 +34,7 @@ endif
tinyclip: $(OBJS) tinyclip: $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS) $(CC) -o $@ $^ $(LDFLAGS)
.PHONY: clean distclean install .PHONY: clean
clean: clean:
$(RM) $(OBJS) $(RM) $(OBJS)
distclean: clean
$(RM) tinyclip
install: tinyclip
install -m 755 tinyclip $(PREFIX)/bin/

19
README
View File

@ -3,25 +3,6 @@
================ ================
A tiny clipboard application for X. A tiny clipboard application for X.
# Building
----------
## Dependencies
To compile the project you will require:
* C99 compatible compiler (GCC is recommended)
* UNIX Make
* X11
## Compiling
The project is built using the `make' command. For debug information
append `DEBUG=1' to the command.
# Installation
--------------
Once the project is built, you can install by running `make install'. By
default the `PREFIX' variable is set to `/usr/local' (installing the
binary in `/usr/local/bin'). You can override this by appending
`PREFIX=<prefix>' to the install command.
# License # License
--------- ---------
This project is licensed under the GNU General Public License version 3 This project is licensed under the GNU General Public License version 3

5
TODO
View File

@ -1,5 +0,0 @@
============
*** TODO ***
============
- Setup response for INCR
- Implement most common plain text targets

View File

@ -19,114 +19,41 @@
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
Display *display;
Window clip_win;
int run; int run;
void *data; void *data;
size_t data_size; size_t data_size;
void quit() { void quit() {
run = 0; run = 0;
XClientMessageEvent cme;
cme.type = ClientMessage;
cme.format = 32;
XSendEvent(display, clip_win, 0, 0, (XEvent*)&cme);
XFlush(display);
} }
void get_selection(Atom property) { void send_selection(Display *display, XSelectionRequestEvent *sre, Atom utf8) {
Atom da, incr, type; XSelectionEvent se;
int di; time_t now_tm;
unsigned long size, dul; char *now;
unsigned char *prop_ret = NULL;
XGetWindowProperty(display, clip_win, property, 0, 0, 0, AnyPropertyType, now_tm = time(NULL);
&type, &di, &dul, &size, &prop_ret); now = ctime(&now_tm);
XFree(prop_ret);
incr = XInternAtom(display, "INCR", 0);
if(type == incr)
{
// TODO: prepare for multiple messages
return;
}
#ifdef DEBUG #ifdef DEBUG
printf("Property size: %lu\n", size); char *an = XGetAtomName(display, sre->property);
#endif printf("Sending CLIPBOARD to window 0x%1x, property '%s'\n", sre->requestor, an);
XGetWindowProperty(display, clip_win, property, 0, size, 0, AnyPropertyType, if(an)
&da, &di, &dul, &dul, &prop_ret); XFree(an);
free(data);
data = malloc(size);
strcpy(data, (void*)prop_ret);
data_size = size;
#ifdef DEBUG
printf("Received data: %s\n", (char*)data);
#endif
XFree(prop_ret);
XDeleteProperty(display, clip_win, property);
}
void send_reject(XSelectionRequestEvent *sre) {
XSelectionEvent reply_se;
#ifdef DEBUG
char *target_name;
target_name = XGetAtomName(display, sre->target);
printf("Denying request for type `%s'\n", target_name);
if(target_name)
XFree(target_name);
#endif #endif
reply_se.type = SelectionNotify; XChangeProperty(display, sre->requestor, sre->property, utf8, 8, PropModeReplace, data, data_size);
reply_se.requestor = sre->requestor;
reply_se.selection = sre->selection;
reply_se.target = sre->target;
reply_se.property = None;
reply_se.time = sre->time;
XSendEvent(display, sre->requestor, 1,
NoEventMask, (XEvent*)&reply_se);
}
void send_selection(XSelectionRequestEvent *sre, Atom target)
{
XSelectionEvent reply_se;
#ifdef DEBUG
char *target_name = XGetAtomName(display, sre->property);
printf("Sending CLIPBOARD to window 0x%1x, property '%s'\n",
(unsigned int)sre->requestor, target_name);
if(target_name)
XFree(target_name);
#endif
XChangeProperty(display, sre->requestor, sre->property,
target, 8, PropModeReplace, (unsigned char*)data, data_size);
reply_se.type = SelectionNotify;
reply_se.requestor = sre->requestor;
reply_se.selection = sre->selection;
reply_se.target = sre->target;
reply_se.property = sre->property;
reply_se.time = sre->time;
XSendEvent(display, sre->requestor, 1,
NoEventMask, (XEvent*)&reply_se);
} }
int main() { int main() {
Window root, owner; Display *display;
Window clip_win, root, owner;
int screen; int screen;
Atom selection, clip_property; Atom selection, utf8, clip_property;
// target atoms XEvent event;
Atom utf8_target;//, text_target, string_target;
data = NULL;
data_size = 0;
// get current X display // get current X display
display = XOpenDisplay(NULL); display = XOpenDisplay(NULL);
@ -141,13 +68,11 @@ int main() {
// create a dummy window for tinyclip // create a dummy window for tinyclip
clip_win = XCreateSimpleWindow(display, root, -10, -10, 1, 1, 0, 0, 0); clip_win = XCreateSimpleWindow(display, root, -10, -10, 1, 1, 0, 0, 0);
XSelectInput(display, clip_win, XSelectInput(display, clip_win,
SelectionClear | SelectionRequest | SelectionNotify | ClientMessage); SelectionClear | SelectionRequest | SelectionNotify);
// create atoms for selections // create atoms for selections
selection = XInternAtom(display, "CLIPBOARD", 0); selection = XInternAtom(display, "CLIPBOARD", 0);
utf8_target = XInternAtom(display, "UTF8_STRING", 0); utf8 = XInternAtom(display, "UTF8_STRING", 0);
//text_target = XInternAtom(display, "TEXT", 0);
//string_target = XInternAtom(display, "STRING", 0);
clip_property = XInternAtom(display, "TINYCLIP", 0); clip_property = XInternAtom(display, "TINYCLIP", 0);
// check if there is currently someone using the clipboard // check if there is currently someone using the clipboard
@ -156,9 +81,9 @@ int main() {
{ {
// take ownership of clipboard while copying contents // take ownership of clipboard while copying contents
#ifdef DEBUG #ifdef DEBUG
printf("Current owner: 0x%1X\n", (unsigned int)owner); printf("Current owner: 0x%1X\n", owner);
#endif #endif
XConvertSelection(display, selection, utf8_target, XConvertSelection(display, selection, utf8,
clip_property, clip_win, CurrentTime); clip_property, clip_win, CurrentTime);
} }
else else
@ -169,29 +94,29 @@ int main() {
run = 1; run = 1;
signal(SIGINT, quit); signal(SIGINT, quit);
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(display, clip_win, &wmDeleteMessage, 1);
while(run) while(run)
{ {
XEvent event; XNextEvent(display, &event);
XSelectionRequestEvent *sre; XSelectionRequestEvent *sre;
XSelectionEvent *se; XSelectionEvent *se;
XNextEvent(display, &event);
switch(event.type) switch(event.type)
{ {
case SelectionClear: case SelectionClear:
// if someone else took the clipboard, regain ownership // if someone else took the clipboard, regain ownership
XConvertSelection(display, selection, utf8_target, #ifdef DEBUG
printf("Lost selection.\n");
#endif
XConvertSelection(display, selection, utf8,
clip_property, clip_win, CurrentTime); clip_property, clip_win, CurrentTime);
break; break;
case SelectionNotify: case SelectionNotify:
// we've been sent the new CLIPBOARD, now we take ownership of it
se = (XSelectionEvent*)&event.xselection; se = (XSelectionEvent*)&event.xselection;
if(se->property == None) if(se->property == None)
fprintf(stderr, "Conversion impossible."); fprintf(stderr, "Conversion impossible.");
else else
get_selection(clip_property); {
// TODO: handle new clipboard information
}
XSetSelectionOwner(display, selection, clip_win, CurrentTime); XSetSelectionOwner(display, selection, clip_win, CurrentTime);
break; break;
case SelectionRequest: case SelectionRequest:
@ -199,14 +124,9 @@ int main() {
sre = (XSelectionRequestEvent*) &event.xselectionrequest; sre = (XSelectionRequestEvent*) &event.xselectionrequest;
#ifdef DEBUG #ifdef DEBUG
printf("New selection request:\n" printf("New selection request:\n"
" requestor: 0x%1x\n", (unsigned int)sre->requestor); " requestor: 0x%1x\n", sre->requestor);
#endif #endif
if(sre->target != utf8_target || sre->property == None) send_selection(display, sre, utf8);
send_reject(sre);
else
send_selection(sre, utf8_target);
break;
case ClientMessage:
break; break;
} }
} }