Rewrite X11 snarf. Maybe this will be better.
This commit is contained in:
parent
a43c1e6fab
commit
54ca86f879
386
gui-x11/screen.c
386
gui-x11/screen.c
|
@ -81,7 +81,7 @@ static void xmouse(XEvent*);
|
||||||
static void xkeyboard(XEvent*);
|
static void xkeyboard(XEvent*);
|
||||||
static void xmapping(XEvent*);
|
static void xmapping(XEvent*);
|
||||||
static void xdestroy(XEvent*);
|
static void xdestroy(XEvent*);
|
||||||
static void xselect(XEvent*);
|
static void xselect(XEvent*, Display*);
|
||||||
static void xproc(void*);
|
static void xproc(void*);
|
||||||
static Memimage* xinitscreen(void);
|
static Memimage* xinitscreen(void);
|
||||||
static void initmap(Window);
|
static void initmap(Window);
|
||||||
|
@ -89,9 +89,9 @@ static GC creategc(Drawable);
|
||||||
static void graphicscmap(XColor*);
|
static void graphicscmap(XColor*);
|
||||||
int xscreendepth;
|
int xscreendepth;
|
||||||
Drawable xscreenid;
|
Drawable xscreenid;
|
||||||
Display* xdisplay;
|
Display* xdisplay; /* used holding draw lock */
|
||||||
Display* xkmcon;
|
Display* xkmcon; /* used only in xproc */
|
||||||
Display* xsnarfcon;
|
Display* xsnarfcon; /* used holding clip.lk */
|
||||||
Visual *xvis;
|
Visual *xvis;
|
||||||
GC xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc;
|
GC xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc;
|
||||||
GC xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0;
|
GC xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0;
|
||||||
|
@ -99,6 +99,8 @@ static void graphicscmap(XColor*);
|
||||||
ulong xwhite;
|
ulong xwhite;
|
||||||
ulong xscreenchan;
|
ulong xscreenchan;
|
||||||
|
|
||||||
|
static int putsnarf, assertsnarf;
|
||||||
|
|
||||||
extern Memimage* xallocmemimage(IRectangle, ulong, int);
|
extern Memimage* xallocmemimage(IRectangle, ulong, int);
|
||||||
Memimage *gscreen;
|
Memimage *gscreen;
|
||||||
Screeninfo screen;
|
Screeninfo screen;
|
||||||
|
@ -134,6 +136,7 @@ attachscreen(IRectangle *r, ulong *chan, int *depth,
|
||||||
void
|
void
|
||||||
flushmemscreen(IRectangle r)
|
flushmemscreen(IRectangle r)
|
||||||
{
|
{
|
||||||
|
assert(!drawcanqlock());
|
||||||
if(r.min.x >= r.max.x || r.min.y >= r.max.y)
|
if(r.min.x >= r.max.x || r.min.y >= r.max.y)
|
||||||
return;
|
return;
|
||||||
XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y);
|
XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y);
|
||||||
|
@ -160,8 +163,10 @@ revbyte(int b)
|
||||||
void
|
void
|
||||||
mouseset(IPoint xy)
|
mouseset(IPoint xy)
|
||||||
{
|
{
|
||||||
|
drawqlock();
|
||||||
XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
|
XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
|
||||||
XFlush(xdisplay);
|
XFlush(xdisplay);
|
||||||
|
drawqunlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Cursor xcursor;
|
static Cursor xcursor;
|
||||||
|
@ -180,6 +185,7 @@ setcursor(void)
|
||||||
mask[i] = revbyte(cursor.set[i] | cursor.clr[i]);
|
mask[i] = revbyte(cursor.set[i] | cursor.clr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawqlock();
|
||||||
fg = map[0];
|
fg = map[0];
|
||||||
bg = map[255];
|
bg = map[255];
|
||||||
xsrc = XCreateBitmapFromData(xdisplay, xdrawable, src, 16, 16);
|
xsrc = XCreateBitmapFromData(xdisplay, xdrawable, src, 16, 16);
|
||||||
|
@ -194,17 +200,20 @@ setcursor(void)
|
||||||
XFreePixmap(xdisplay, xsrc);
|
XFreePixmap(xdisplay, xsrc);
|
||||||
XFreePixmap(xdisplay, xmask);
|
XFreePixmap(xdisplay, xmask);
|
||||||
XFlush(xdisplay);
|
XFlush(xdisplay);
|
||||||
|
drawqunlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursorarrow(void)
|
cursorarrow(void)
|
||||||
{
|
{
|
||||||
|
drawqlock();
|
||||||
if(xcursor != 0){
|
if(xcursor != 0){
|
||||||
XFreeCursor(xdisplay, xcursor);
|
XFreeCursor(xdisplay, xcursor);
|
||||||
xcursor = 0;
|
xcursor = 0;
|
||||||
}
|
}
|
||||||
XUndefineCursor(xdisplay, xdrawable);
|
XUndefineCursor(xdisplay, xdrawable);
|
||||||
XFlush(xdisplay);
|
XFlush(xdisplay);
|
||||||
|
drawqunlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -229,7 +238,7 @@ xproc(void *arg)
|
||||||
for(;;) {
|
for(;;) {
|
||||||
//XWindowEvent(xkmcon, xdrawable, mask, &event);
|
//XWindowEvent(xkmcon, xdrawable, mask, &event);
|
||||||
XNextEvent(xkmcon, &event);
|
XNextEvent(xkmcon, &event);
|
||||||
xselect(&event);
|
xselect(&event, xkmcon);
|
||||||
xkeyboard(&event);
|
xkeyboard(&event);
|
||||||
xmouse(&event);
|
xmouse(&event);
|
||||||
xexpose(&event);
|
xexpose(&event);
|
||||||
|
@ -624,13 +633,6 @@ xdestroy(XEvent *e)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
xselection(XEvent *e)
|
|
||||||
{
|
|
||||||
XSelectionRequestEvent *xre;
|
|
||||||
XSelectionEvent *xe;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xmapping(XEvent *e)
|
xmapping(XEvent *e)
|
||||||
{
|
{
|
||||||
|
@ -691,7 +693,7 @@ xkeyboard(XEvent *e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
XLookupString(e,NULL,0,&k,NULL);
|
XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL);
|
||||||
|
|
||||||
if(k == XK_Multi_key || k == NoSymbol)
|
if(k == XK_Multi_key || k == NoSymbol)
|
||||||
return;
|
return;
|
||||||
|
@ -785,8 +787,10 @@ xkeyboard(XEvent *e)
|
||||||
default: /* not ISO-1 or tty control */
|
default: /* not ISO-1 or tty control */
|
||||||
if(k>0xff){
|
if(k>0xff){
|
||||||
k = keysym2ucs(k); /* supplied by X */
|
k = keysym2ucs(k); /* supplied by X */
|
||||||
if(k == -1) return;
|
if(k == -1)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,9 +815,27 @@ xmouse(XEvent *e)
|
||||||
XButtonEvent *be;
|
XButtonEvent *be;
|
||||||
XMotionEvent *me;
|
XMotionEvent *me;
|
||||||
|
|
||||||
|
if(putsnarf != assertsnarf){
|
||||||
|
assertsnarf = putsnarf;
|
||||||
|
XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime);
|
||||||
|
if(clipboard != None)
|
||||||
|
XSetSelectionOwner(xkmcon, clipboard, xdrawable, CurrentTime);
|
||||||
|
XFlush(xkmcon);
|
||||||
|
}
|
||||||
|
|
||||||
switch(e->type){
|
switch(e->type){
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
be = (XButtonEvent *)e;
|
be = (XButtonEvent *)e;
|
||||||
|
/*
|
||||||
|
* Fake message, just sent to make us announce snarf.
|
||||||
|
* Apparently state and button are 16 and 8 bits on
|
||||||
|
* the wire, since they are truncated by the time they
|
||||||
|
* get to us.
|
||||||
|
*/
|
||||||
|
if(be->send_event
|
||||||
|
&& (~be->state&0xFFFF)==0
|
||||||
|
&& (~be->button&0xFF)==0)
|
||||||
|
return;
|
||||||
ms.xy.x = be->x;
|
ms.xy.x = be->x;
|
||||||
ms.xy.y = be->y;
|
ms.xy.y = be->y;
|
||||||
s = be->state;
|
s = be->state;
|
||||||
|
@ -921,154 +943,16 @@ setcolor(ulong i, ulong r, ulong g, ulong b)
|
||||||
/* no-op */
|
/* no-op */
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct Clip Clip;
|
|
||||||
struct Clip
|
|
||||||
{
|
|
||||||
char buf[SnarfSize];
|
|
||||||
ulong n;
|
|
||||||
int want, have;
|
|
||||||
QLock lk;
|
|
||||||
Rendez vous;
|
|
||||||
};
|
|
||||||
|
|
||||||
Clip clip;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
Chunk = 2048
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
xselect(XEvent *e)
|
|
||||||
{
|
|
||||||
XSelectionRequestEvent *q;
|
|
||||||
XEvent r;
|
|
||||||
Atom a[4];
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
|
|
||||||
if(e->type != SelectionRequest)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The lock is around the whole routine because we use the
|
|
||||||
* lock to make sure two people aren't sending on xkmcon
|
|
||||||
* at once.
|
|
||||||
*/
|
|
||||||
q = (XSelectionRequestEvent*)e;
|
|
||||||
|
|
||||||
r.xselection.property = q->property;
|
|
||||||
if(q->target == targets) {
|
|
||||||
a[0] = XA_STRING;
|
|
||||||
a[1] = utf8string;
|
|
||||||
a[2] = text;
|
|
||||||
a[3] = compoundtext;
|
|
||||||
|
|
||||||
XChangeProperty(xkmcon, q->requestor, q->property, q->target,
|
|
||||||
8, PropModeReplace, (uchar*)a, sizeof a);
|
|
||||||
}else if(q->target == XA_STRING || q->target == utf8string || q->target == text || q->target == compoundtext){
|
|
||||||
qlock(&clip.lk);
|
|
||||||
XChangeProperty(xkmcon, q->requestor, q->property, q->target, 8,
|
|
||||||
PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
|
|
||||||
qunlock(&clip.lk);
|
|
||||||
}else {
|
|
||||||
name = XGetAtomName(xkmcon, q->target);
|
|
||||||
if(strcmp(name, "TIMESTAMP") != 0)
|
|
||||||
fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)q->target);
|
|
||||||
r.xselection.property = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
r.xselection.type = SelectionNotify;
|
|
||||||
r.xselection.display = q->display;
|
|
||||||
r.xselection.requestor = q->requestor;
|
|
||||||
r.xselection.selection = q->selection;
|
|
||||||
r.xselection.target = q->target;
|
|
||||||
r.xselection.time = q->time;
|
|
||||||
XSendEvent(xkmcon, q->requestor, False, 0, &r);
|
|
||||||
XFlush(xkmcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
haveclip(void *a)
|
|
||||||
{
|
|
||||||
return clip.want == clip.have;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef long /* sic */
|
|
||||||
char*
|
|
||||||
clipread(void)
|
|
||||||
{
|
|
||||||
Window w;
|
|
||||||
XEvent e;
|
|
||||||
Atom type;
|
|
||||||
unsigned long len, lleft, left, dummy;
|
|
||||||
int i, fmt, res;
|
|
||||||
uchar *data;
|
|
||||||
|
|
||||||
qlock(&clip.lk);
|
|
||||||
w = XGetSelectionOwner(xsnarfcon, XA_PRIMARY);
|
|
||||||
if(w == xdrawable)
|
|
||||||
data = (uchar*)strdup(clip.buf);
|
|
||||||
else if(w == None)
|
|
||||||
data = nil;
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* we're supposed to get a notification, but we seem not to,
|
|
||||||
* so let's just watch and see when the buffer stabilizes.
|
|
||||||
* if you know how to fix this, mail rsc@plan9.bell-labs.com.
|
|
||||||
*/
|
|
||||||
XChangeProperty(xsnarfcon, xdrawable, XA_PRIMARY, XA_STRING, 8, PropModeReplace,
|
|
||||||
(uchar*)"", 0);
|
|
||||||
XConvertSelection(xsnarfcon, XA_PRIMARY, XA_STRING, None, xdrawable, CurrentTime);
|
|
||||||
XFlush(xsnarfcon);
|
|
||||||
for(i=0; i<30; i++){
|
|
||||||
osmsleep(100);
|
|
||||||
XGetWindowProperty(xsnarfcon, xdrawable, XA_STRING, 0, 0, 0, AnyPropertyType,
|
|
||||||
&type, &fmt, &len, &left, &data);
|
|
||||||
if(lleft == left && left > 0)
|
|
||||||
break;
|
|
||||||
lleft = left;
|
|
||||||
}
|
|
||||||
if(left > 0){
|
|
||||||
res = XGetWindowProperty(xsnarfcon, xdrawable, XA_STRING, 0, left, 0,
|
|
||||||
AnyPropertyType, &type, &fmt, &len, &dummy, &data);
|
|
||||||
data = (uchar*)strdup(data);
|
|
||||||
}else
|
|
||||||
data = nil;
|
|
||||||
}
|
|
||||||
qunlock(&clip.lk);
|
|
||||||
return (char*)data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
clipwrite(char *buf)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = strlen(buf);
|
|
||||||
qlock(&clip.lk);
|
|
||||||
if(n >= SnarfSize)
|
|
||||||
n = SnarfSize - 1;
|
|
||||||
memmove(clip.buf, buf, n);
|
|
||||||
clip.buf[n] = 0;
|
|
||||||
clip.n = n;
|
|
||||||
/*
|
|
||||||
* xkmcon so that we get the event in the select loop.
|
|
||||||
* It seems to be okay to send a message and read an event
|
|
||||||
* from a Display* at the same time. Let's hope so.
|
|
||||||
*/
|
|
||||||
XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime);
|
|
||||||
XFlush(xkmcon);
|
|
||||||
qunlock(&clip.lk);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
#define long int /* sic */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
atlocalconsole(void)
|
atlocalconsole(void)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
|
p = getenv("DRAWTERM_ATLOCALCONSOLE");
|
||||||
|
if(p && atoi(p) == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
p = getenv("DISPLAY");
|
p = getenv("DISPLAY");
|
||||||
if(p == nil)
|
if(p == nil)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1092,3 +976,193 @@ atlocalconsole(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cut and paste. Just couldn't stand to make this simple...
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct Clip Clip;
|
||||||
|
struct Clip
|
||||||
|
{
|
||||||
|
char buf[SnarfSize];
|
||||||
|
QLock lk;
|
||||||
|
};
|
||||||
|
Clip clip;
|
||||||
|
|
||||||
|
#undef long /* sic */
|
||||||
|
#undef ulong
|
||||||
|
|
||||||
|
static char*
|
||||||
|
_xgetsnarf(Display *xd)
|
||||||
|
{
|
||||||
|
uchar *data, *xdata;
|
||||||
|
Atom clipboard, type, prop;
|
||||||
|
ulong len, lastlen, dummy;
|
||||||
|
int fmt, i;
|
||||||
|
Window w;
|
||||||
|
|
||||||
|
qlock(&clip.lk);
|
||||||
|
/*
|
||||||
|
* Have we snarfed recently and the X server hasn't caught up?
|
||||||
|
*/
|
||||||
|
if(putsnarf != assertsnarf)
|
||||||
|
goto mine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is there a primary selection (highlighted text in an xterm)?
|
||||||
|
*/
|
||||||
|
clipboard = XA_PRIMARY;
|
||||||
|
w = XGetSelectionOwner(xd, XA_PRIMARY);
|
||||||
|
if(w == xdrawable){
|
||||||
|
mine:
|
||||||
|
data = (uchar*)strdup(clip.buf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If not, is there a clipboard selection?
|
||||||
|
*/
|
||||||
|
if(w == None && clipboard != None){
|
||||||
|
clipboard = clipboard;
|
||||||
|
w = XGetSelectionOwner(xd, clipboard);
|
||||||
|
if(w == xdrawable)
|
||||||
|
goto mine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If not, give up.
|
||||||
|
*/
|
||||||
|
if(w == None){
|
||||||
|
data = nil;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We should be waiting for SelectionNotify here, but it might never
|
||||||
|
* come, and we have no way to time out. Instead, we will clear
|
||||||
|
* local property #1, request our buddy to fill it in for us, and poll
|
||||||
|
* until he's done or we get tired of waiting.
|
||||||
|
*
|
||||||
|
* We should try to go for utf8string instead of XA_STRING,
|
||||||
|
* but that would add to the polling.
|
||||||
|
*/
|
||||||
|
prop = 1;
|
||||||
|
XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
|
||||||
|
XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime);
|
||||||
|
XFlush(xd);
|
||||||
|
lastlen = 0;
|
||||||
|
for(i=0; i<10 || (lastlen!=0 && i<30); i++){
|
||||||
|
usleep(100*1000);
|
||||||
|
XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType,
|
||||||
|
&type, &fmt, &dummy, &len, &data);
|
||||||
|
if(lastlen == len && len > 0)
|
||||||
|
break;
|
||||||
|
lastlen = len;
|
||||||
|
}
|
||||||
|
if(i == 10){
|
||||||
|
data = nil;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* get the property */
|
||||||
|
data = nil;
|
||||||
|
XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(ulong), 0,
|
||||||
|
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
|
||||||
|
if((type != XA_STRING && type != utf8string) || len == 0){
|
||||||
|
if(xdata)
|
||||||
|
XFree(xdata);
|
||||||
|
data = nil;
|
||||||
|
}else{
|
||||||
|
if(xdata){
|
||||||
|
data = (uchar*)strdup((char*)xdata);
|
||||||
|
XFree(xdata);
|
||||||
|
}else
|
||||||
|
data = nil;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
qunlock(&clip.lk);
|
||||||
|
return (char*)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_xputsnarf(Display *xd, char *data)
|
||||||
|
{
|
||||||
|
XButtonEvent e;
|
||||||
|
|
||||||
|
if(strlen(data) >= SnarfSize)
|
||||||
|
return;
|
||||||
|
qlock(&clip.lk);
|
||||||
|
strcpy(clip.buf, data);
|
||||||
|
|
||||||
|
/* leave note for mouse proc to assert selection ownership */
|
||||||
|
putsnarf++;
|
||||||
|
|
||||||
|
/* send mouse a fake event so snarf is announced */
|
||||||
|
memset(&e, 0, sizeof e);
|
||||||
|
e.type = ButtonPress;
|
||||||
|
e.window = xdrawable;
|
||||||
|
e.state = ~0;
|
||||||
|
e.button = ~0;
|
||||||
|
XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e);
|
||||||
|
XFlush(xd);
|
||||||
|
qunlock(&clip.lk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xselect(XEvent *e, Display *xd)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
XEvent r;
|
||||||
|
XSelectionRequestEvent *xe;
|
||||||
|
Atom a[4];
|
||||||
|
|
||||||
|
memset(&r, 0, sizeof r);
|
||||||
|
xe = (XSelectionRequestEvent*)e;
|
||||||
|
if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d\n",
|
||||||
|
xe->target, xe->requestor, xe->property, xe->selection);
|
||||||
|
r.xselection.property = xe->property;
|
||||||
|
if(xe->target == targets){
|
||||||
|
a[0] = XA_STRING;
|
||||||
|
a[1] = utf8string;
|
||||||
|
a[2] = text;
|
||||||
|
a[3] = compoundtext;
|
||||||
|
|
||||||
|
XChangeProperty(xd, xe->requestor, xe->property, xe->target,
|
||||||
|
8, PropModeReplace, (uchar*)a, sizeof a);
|
||||||
|
}else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){
|
||||||
|
/* if the target is STRING we're supposed to reply with Latin1 XXX */
|
||||||
|
qlock(&clip.lk);
|
||||||
|
XChangeProperty(xd, xe->requestor, xe->property, xe->target,
|
||||||
|
8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
|
||||||
|
qunlock(&clip.lk);
|
||||||
|
}else{
|
||||||
|
name = XGetAtomName(xd, xe->target);
|
||||||
|
if(strcmp(name, "TIMESTAMP") != 0)
|
||||||
|
fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
|
||||||
|
r.xselection.property = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.xselection.display = xe->display;
|
||||||
|
/* r.xselection.property filled above */
|
||||||
|
r.xselection.target = xe->target;
|
||||||
|
r.xselection.type = SelectionNotify;
|
||||||
|
r.xselection.requestor = xe->requestor;
|
||||||
|
r.xselection.time = xe->time;
|
||||||
|
r.xselection.send_event = True;
|
||||||
|
r.xselection.selection = xe->selection;
|
||||||
|
XSendEvent(xd, xe->requestor, False, 0, &r);
|
||||||
|
XFlush(xd);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
clipread(void)
|
||||||
|
{
|
||||||
|
return _xgetsnarf(xsnarfcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clipwrite(char *buf)
|
||||||
|
{
|
||||||
|
_xputsnarf(xsnarfcon, buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,24 @@ static char Eoldname[] = "named image no longer valid";
|
||||||
static char Enamed[] = "image already has name";
|
static char Enamed[] = "image already has name";
|
||||||
static char Ewrongname[] = "wrong name for image";
|
static char Ewrongname[] = "wrong name for image";
|
||||||
|
|
||||||
|
int
|
||||||
|
drawcanqlock(void)
|
||||||
|
{
|
||||||
|
return canqlock(&sdraw.lk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drawqlock(void)
|
||||||
|
{
|
||||||
|
qlock(&sdraw.lk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drawqunlock(void)
|
||||||
|
{
|
||||||
|
qunlock(&sdraw.lk);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp)
|
drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,6 +79,9 @@ Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
|
||||||
int devwstat(Chan*, uchar*, int);
|
int devwstat(Chan*, uchar*, int);
|
||||||
void drawactive(int);
|
void drawactive(int);
|
||||||
void drawcmap(void);
|
void drawcmap(void);
|
||||||
|
int drawcanqlock(void);
|
||||||
|
void drawqlock(void);
|
||||||
|
void drawqunlock(void);
|
||||||
void dumpaproc(Proc*);
|
void dumpaproc(Proc*);
|
||||||
void dumpqueues(void);
|
void dumpqueues(void);
|
||||||
void dumpregs(Ureg*);
|
void dumpregs(Ureg*);
|
||||||
|
|
Loading…
Reference in New Issue