mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-24 11:41:58 +00:00
devdraw: more cleanup, clearer locking
This commit is contained in:
parent
b1a086dee9
commit
41547af3f6
8 changed files with 331 additions and 315 deletions
|
@ -14,14 +14,12 @@
|
|||
#include <drawfcall.h>
|
||||
#include "devdraw.h"
|
||||
|
||||
static Draw sdraw;
|
||||
Client *client0;
|
||||
static int drawuninstall(Client*, int);
|
||||
static Memimage* drawinstall(Client*, int, Memimage*, DScreen*);
|
||||
static void drawfreedimage(Client*, DImage*);
|
||||
|
||||
void
|
||||
_initdisplaymemimage(Client *c, Memimage *m)
|
||||
draw_initdisplaymemimage(Client *c, Memimage *m)
|
||||
{
|
||||
c->screenimage = m;
|
||||
m->screenref = 1;
|
||||
|
@ -30,10 +28,10 @@ _initdisplaymemimage(Client *c, Memimage *m)
|
|||
c->op = SoverD;
|
||||
}
|
||||
|
||||
// _drawreplacescreen replaces c's screen image with m.
|
||||
// gfx_replacescreenimage replaces c's screen image with m.
|
||||
// It is called by the host driver on the main host thread.
|
||||
void
|
||||
_drawreplacescreenimage(Client *c, Memimage *m)
|
||||
gfx_replacescreenimage(Client *c, Memimage *m)
|
||||
{
|
||||
/*
|
||||
* Replace the screen image because the screen
|
||||
|
@ -49,21 +47,21 @@ _drawreplacescreenimage(Client *c, Memimage *m)
|
|||
*/
|
||||
Memimage *om;
|
||||
|
||||
qlock(&c->inputlk);
|
||||
qlock(&sdraw.lk);
|
||||
qlock(&c->drawlk);
|
||||
om = c->screenimage;
|
||||
c->screenimage = m;
|
||||
m->screenref = 1;
|
||||
c->mouse.resized = 1;
|
||||
if(om && --om->screenref == 0){
|
||||
_freememimage(om);
|
||||
}
|
||||
qunlock(&sdraw.lk);
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->drawlk);
|
||||
|
||||
qlock(&c->eventlk);
|
||||
c->mouse.resized = 1;
|
||||
qunlock(&c->eventlk);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawrefreshscreen(DImage *l, Client *client)
|
||||
{
|
||||
while(l != nil && l->dscreen == nil)
|
||||
|
@ -72,8 +70,7 @@ drawrefreshscreen(DImage *l, Client *client)
|
|||
l->dscreen->owner->refreshme = 1;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawrefresh(Memimage *m, Rectangle r, void *v)
|
||||
{
|
||||
Refx *x;
|
||||
|
@ -106,7 +103,7 @@ static void
|
|||
addflush(Client *c, Rectangle r)
|
||||
{
|
||||
int abb, ar, anbb;
|
||||
Rectangle nbb;
|
||||
Rectangle nbb, fr;
|
||||
|
||||
if(/*sdraw.softscreen==0 ||*/ !rectclip(&r, c->screenimage->r))
|
||||
return;
|
||||
|
@ -140,14 +137,20 @@ addflush(Client *c, Rectangle r)
|
|||
return;
|
||||
}
|
||||
/* emit current state */
|
||||
if(c->flushrect.min.x < c->flushrect.max.x)
|
||||
rpc_flushmemscreen(c, c->flushrect);
|
||||
fr = c->flushrect;
|
||||
c->flushrect = r;
|
||||
c->waste = 0;
|
||||
if(fr.min.x < fr.max.x) {
|
||||
// Unlock drawlk because rpc_flush may want to run on gfx thread,
|
||||
// and gfx thread might be blocked on drawlk trying to install a new screen
|
||||
// during a resize.
|
||||
qunlock(&c->drawlk);
|
||||
rpc_flush(c, fr);
|
||||
qlock(&c->drawlk);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
dstflush(Client *c, int dstid, Memimage *dst, Rectangle r)
|
||||
{
|
||||
Memlayer *l;
|
||||
|
@ -173,17 +176,24 @@ dstflush(Client *c, int dstid, Memimage *dst, Rectangle r)
|
|||
addflush(c, r);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawflush(Client *c)
|
||||
{
|
||||
if(c->flushrect.min.x < c->flushrect.max.x)
|
||||
rpc_flushmemscreen(c, c->flushrect);
|
||||
Rectangle r;
|
||||
|
||||
r = c->flushrect;
|
||||
c->flushrect = Rect(10000, 10000, -10000, -10000);
|
||||
if(r.min.x < r.max.x) {
|
||||
// Unlock drawlk because rpc_flush may want to run on gfx thread,
|
||||
// and gfx thread might be blocked on drawlk trying to install a new screen
|
||||
// during a resize.
|
||||
qunlock(&c->drawlk);
|
||||
rpc_flush(c, r);
|
||||
qlock(&c->drawlk);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
static int
|
||||
drawcmp(char *a, char *b, int n)
|
||||
{
|
||||
if(strlen(a) != n)
|
||||
|
@ -191,8 +201,7 @@ drawcmp(char *a, char *b, int n)
|
|||
return memcmp(a, b, n);
|
||||
}
|
||||
|
||||
static
|
||||
DName*
|
||||
static DName*
|
||||
drawlookupname(Client *client, int n, char *str)
|
||||
{
|
||||
DName *name, *ename;
|
||||
|
@ -205,8 +214,7 @@ drawlookupname(Client *client, int n, char *str)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
static int
|
||||
drawgoodname(Client *client, DImage *d)
|
||||
{
|
||||
DName *n;
|
||||
|
@ -224,8 +232,7 @@ drawgoodname(Client *client, DImage *d)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
DImage*
|
||||
static DImage*
|
||||
drawlookup(Client *client, int id, int checkname)
|
||||
{
|
||||
DImage *d;
|
||||
|
@ -246,8 +253,7 @@ drawlookup(Client *client, int id, int checkname)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
DScreen*
|
||||
static DScreen*
|
||||
drawlookupdscreen(Client *c, int id)
|
||||
{
|
||||
DScreen *s;
|
||||
|
@ -261,8 +267,7 @@ drawlookupdscreen(Client *c, int id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
DScreen*
|
||||
static DScreen*
|
||||
drawlookupscreen(Client *client, int id, CScreen **cs)
|
||||
{
|
||||
CScreen *s;
|
||||
|
@ -279,8 +284,7 @@ drawlookupscreen(Client *client, int id, CScreen **cs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
Memimage*
|
||||
static Memimage*
|
||||
drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
|
||||
{
|
||||
DImage *d;
|
||||
|
@ -304,8 +308,7 @@ drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
|
|||
return i;
|
||||
}
|
||||
|
||||
static
|
||||
Memscreen*
|
||||
static Memscreen*
|
||||
drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
|
||||
{
|
||||
Memscreen *s;
|
||||
|
@ -358,8 +361,7 @@ drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *df
|
|||
return d->screen;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawdelname(Client *client, DName *name)
|
||||
{
|
||||
int i;
|
||||
|
@ -369,8 +371,7 @@ drawdelname(Client *client, DName *name)
|
|||
client->nname--;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawfreedscreen(Client *client, DScreen *this)
|
||||
{
|
||||
DScreen *ds, *next;
|
||||
|
@ -406,8 +407,7 @@ drawfreedscreen(Client *client, DScreen *this)
|
|||
free(this);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawfreedimage(Client *client, DImage *dimage)
|
||||
{
|
||||
int i;
|
||||
|
@ -456,8 +456,7 @@ drawfreedimage(Client *client, DImage *dimage)
|
|||
free(dimage);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawuninstallscreen(Client *client, CScreen *this)
|
||||
{
|
||||
CScreen *cs, *next;
|
||||
|
@ -480,8 +479,7 @@ drawuninstallscreen(Client *client, CScreen *this)
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
static int
|
||||
drawuninstall(Client *client, int id)
|
||||
{
|
||||
DImage *d, **l;
|
||||
|
@ -496,8 +494,7 @@ drawuninstall(Client *client, int id)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
static int
|
||||
drawaddname(Client *client, DImage *di, int n, char *str, char **err)
|
||||
{
|
||||
DName *name, *ename, *new, *t;
|
||||
|
@ -541,8 +538,7 @@ drawclientop(Client *cl)
|
|||
return op;
|
||||
}
|
||||
|
||||
static
|
||||
Memimage*
|
||||
static Memimage*
|
||||
drawimage(Client *client, uchar *a)
|
||||
{
|
||||
DImage *d;
|
||||
|
@ -553,8 +549,7 @@ drawimage(Client *client, uchar *a)
|
|||
return d->image;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawrectangle(Rectangle *r, uchar *a)
|
||||
{
|
||||
r->min.x = BGLONG(a+0*4);
|
||||
|
@ -563,16 +558,14 @@ drawrectangle(Rectangle *r, uchar *a)
|
|||
r->max.y = BGLONG(a+3*4);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
drawpoint(Point *p, uchar *a)
|
||||
{
|
||||
p->x = BGLONG(a+0*4);
|
||||
p->y = BGLONG(a+1*4);
|
||||
}
|
||||
|
||||
static
|
||||
Point
|
||||
static Point
|
||||
drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
|
||||
{
|
||||
FChar *fc;
|
||||
|
@ -592,8 +585,7 @@ drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int ind
|
|||
return p;
|
||||
}
|
||||
|
||||
static
|
||||
uchar*
|
||||
static uchar*
|
||||
drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
|
||||
{
|
||||
int b, x;
|
||||
|
@ -619,9 +611,9 @@ drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
|
|||
}
|
||||
|
||||
int
|
||||
_drawmsgread(Client *cl, void *a, int n)
|
||||
draw_dataread(Client *cl, void *a, int n)
|
||||
{
|
||||
qlock(&sdraw.lk);
|
||||
qlock(&cl->drawlk);
|
||||
if(cl->readdata == nil){
|
||||
werrstr("no draw data");
|
||||
goto err;
|
||||
|
@ -634,16 +626,16 @@ _drawmsgread(Client *cl, void *a, int n)
|
|||
memmove(a, cl->readdata, cl->nreaddata);
|
||||
free(cl->readdata);
|
||||
cl->readdata = nil;
|
||||
qunlock(&sdraw.lk);
|
||||
qunlock(&cl->drawlk);
|
||||
return n;
|
||||
|
||||
err:
|
||||
qunlock(&sdraw.lk);
|
||||
qunlock(&cl->drawlk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
_drawmsgwrite(Client *client, void *v, int n)
|
||||
draw_datawrite(Client *client, void *v, int n)
|
||||
{
|
||||
char cbuf[40], *err, ibuf[12*12+1], *s;
|
||||
int c, ci, doflush, dstid, e0, e1, esize, j, m;
|
||||
|
@ -663,7 +655,7 @@ _drawmsgwrite(Client *client, void *v, int n)
|
|||
Refreshfn reffn;
|
||||
Refx *refx;
|
||||
|
||||
qlock(&sdraw.lk);
|
||||
qlock(&client->drawlk);
|
||||
a = v;
|
||||
m = 0;
|
||||
oldn = n;
|
||||
|
@ -1436,7 +1428,7 @@ _drawmsgwrite(Client *client, void *v, int n)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
qunlock(&sdraw.lk);
|
||||
qunlock(&client->drawlk);
|
||||
return oldn - n;
|
||||
|
||||
Enodrawimage:
|
||||
|
@ -1506,6 +1498,6 @@ Ebadarg:
|
|||
|
||||
error:
|
||||
werrstr("%s", err);
|
||||
qunlock(&sdraw.lk);
|
||||
qunlock(&client->drawlk);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ typedef struct Mousebuf Mousebuf;
|
|||
typedef struct Tagbuf Tagbuf;
|
||||
|
||||
typedef struct Client Client;
|
||||
typedef struct Draw Draw;
|
||||
typedef struct DImage DImage;
|
||||
typedef struct DScreen DScreen;
|
||||
typedef struct CScreen CScreen;
|
||||
|
@ -16,11 +15,6 @@ typedef struct Refresh Refresh;
|
|||
typedef struct Refx Refx;
|
||||
typedef struct DName DName;
|
||||
|
||||
struct Draw
|
||||
{
|
||||
QLock lk;
|
||||
};
|
||||
|
||||
struct Kbdbuf
|
||||
{
|
||||
Rune r[256];
|
||||
|
@ -51,6 +45,19 @@ struct Tagbuf
|
|||
|
||||
struct Client
|
||||
{
|
||||
int rfd;
|
||||
|
||||
// wfdlk protects writes to wfd, which can be issued from either
|
||||
// the RPC thread or the graphics thread.
|
||||
QLock wfdlk;
|
||||
int wfd;
|
||||
uchar* mbuf;
|
||||
int nmbuf;
|
||||
|
||||
// drawlk protects the draw data structures.
|
||||
// It can be acquired by an RPC thread or a graphics thread
|
||||
// but must not be held on one thread while waiting for the other.
|
||||
QLock drawlk;
|
||||
/*Ref r;*/
|
||||
DImage* dimage[NHASH];
|
||||
CScreen* cscreen;
|
||||
|
@ -64,7 +71,6 @@ struct Client
|
|||
int refreshme;
|
||||
int infoid;
|
||||
int op;
|
||||
|
||||
int displaydpi;
|
||||
int forcedpi;
|
||||
int waste;
|
||||
|
@ -75,11 +81,11 @@ struct Client
|
|||
DName* name;
|
||||
int namevers;
|
||||
|
||||
int rfd;
|
||||
int wfd;
|
||||
// Only accessed/modified by the graphics thread.
|
||||
const void* view;
|
||||
|
||||
QLock inputlk;
|
||||
// eventlk protects the keyboard and mouse events.
|
||||
QLock eventlk;
|
||||
Kbdbuf kbd;
|
||||
Mousebuf mouse;
|
||||
Tagbuf kbdtags;
|
||||
|
@ -157,30 +163,59 @@ struct DScreen
|
|||
DScreen* next;
|
||||
};
|
||||
|
||||
int _drawmsgread(Client*, void*, int);
|
||||
int _drawmsgwrite(Client*, void*, int);
|
||||
void _initdisplaymemimage(Client*, Memimage*);
|
||||
void _drawreplacescreenimage(Client*, Memimage*);
|
||||
|
||||
int _latin1(Rune*, int);
|
||||
int parsewinsize(char*, Rectangle*, int*);
|
||||
int mouseswap(int);
|
||||
// For the most part, the graphics driver-specific code in files
|
||||
// like mac-screen.m runs in the graphics library's main thread,
|
||||
// while the RPC service code in srv.c runs on the RPC service thread.
|
||||
// The exceptions in each file, which are called by the other,
|
||||
// are marked with special prefixes: gfx_* indicates code that
|
||||
// is in srv.c but nonetheless runs on the main graphics thread,
|
||||
// while rpc_* indicates code that is in, say, mac-screen.m but
|
||||
// nonetheless runs on the RPC service thread.
|
||||
//
|
||||
// The gfx_* and rpc_* calls typically synchronize with the other
|
||||
// code in the file by acquiring a lock (or running a callback on the
|
||||
// target thread, which amounts to the same thing).
|
||||
// To avoid deadlock, callers of those routines must not hold any locks.
|
||||
|
||||
// gfx_* routines are called on the graphics thread,
|
||||
// invoked from graphics driver callbacks to do RPC work.
|
||||
// No locks are held on entry.
|
||||
void gfx_abortcompose(Client*);
|
||||
void gfx_keystroke(Client*, int);
|
||||
void gfx_main(void);
|
||||
void gfx_mousetrack(Client*, int, int, int, uint);
|
||||
void gfx_replacescreenimage(Client*, Memimage*);
|
||||
void gfx_started(void);
|
||||
|
||||
void rpc_setmouse(Client*, Point);
|
||||
void rpc_setcursor(Client*, Cursor*, Cursor2*);
|
||||
void rpc_setlabel(Client*, char*);
|
||||
void rpc_resizeimg(Client*);
|
||||
void rpc_resizewindow(Client*, Rectangle);
|
||||
void rpc_topwin(Client*);
|
||||
// rpc_* routines are called on the RPC thread,
|
||||
// invoked by the RPC server code to do graphics work.
|
||||
// No locks are held on entry.
|
||||
Memimage *rpc_attach(Client*, char*, char*);
|
||||
char* rpc_getsnarf(void);
|
||||
void rpc_putsnarf(char*);
|
||||
Memimage *rpc_attachscreen(Client*, char*, char*);
|
||||
void rpc_flushmemscreen(Client*, Rectangle);
|
||||
void rpc_resizeimg(Client*);
|
||||
void rpc_resizewindow(Client*, Rectangle);
|
||||
void rpc_serve(Client*);
|
||||
void rpc_setcursor(Client*, Cursor*, Cursor2*);
|
||||
void rpc_setlabel(Client*, char*);
|
||||
void rpc_setmouse(Client*, Point);
|
||||
void rpc_shutdown(void);
|
||||
void rpc_topwin(Client*);
|
||||
void rpc_main(void);
|
||||
|
||||
extern Client *client0;
|
||||
// TODO: rpc_flush is called from draw_datawrite,
|
||||
// which holds c->drawlk. Is this OK?
|
||||
void rpc_flush(Client*, Rectangle);
|
||||
|
||||
// draw* routines are called on the RPC thread,
|
||||
// invoked by the RPC server to do pixel pushing.
|
||||
// c->drawlk is held on entry.
|
||||
int draw_dataread(Client*, void*, int);
|
||||
int draw_datawrite(Client*, void*, int);
|
||||
void draw_initdisplaymemimage(Client*, Memimage*);
|
||||
|
||||
// utility routines
|
||||
int latin1(Rune*, int);
|
||||
int mouseswap(int);
|
||||
int parsewinsize(char*, Rectangle*, int*);
|
||||
|
||||
void servep9p(Client*);
|
||||
|
|
|
@ -46,7 +46,7 @@ unicode(Rune *k)
|
|||
* is minus the required n.
|
||||
*/
|
||||
int
|
||||
_latin1(Rune *k, int n)
|
||||
latin1(Rune *k, int n)
|
||||
{
|
||||
struct cvlist *l;
|
||||
int c;
|
||||
|
|
|
@ -34,13 +34,6 @@ static void setprocname(const char*);
|
|||
static uint keycvt(uint);
|
||||
static uint msec(void);
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: devdraw (don't run directly)\n");
|
||||
threadexitsall("usage");
|
||||
}
|
||||
|
||||
@class DrawView;
|
||||
@class DrawLayer;
|
||||
|
||||
|
@ -49,43 +42,9 @@ usage(void)
|
|||
|
||||
static AppDelegate *myApp = NULL;
|
||||
|
||||
|
||||
static QLock snarfl;
|
||||
|
||||
void
|
||||
threadmain(int argc, char **argv)
|
||||
gfx_main(void)
|
||||
{
|
||||
/*
|
||||
* Move the protocol off stdin/stdout so that
|
||||
* any inadvertent prints don't screw things up.
|
||||
*/
|
||||
dup(0,3);
|
||||
dup(1,4);
|
||||
close(0);
|
||||
close(1);
|
||||
open("/dev/null", OREAD);
|
||||
open("/dev/null", OWRITE);
|
||||
|
||||
ARGBEGIN{
|
||||
case 'D': /* for good ps -a listings */
|
||||
break;
|
||||
case 'f': /* fall through for backward compatibility */
|
||||
case 'g':
|
||||
case 'b':
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
client0 = mallocz(sizeof(Client), 1);
|
||||
if(client0 == nil){
|
||||
fprint(2, "initdraw: allocating client0: out of memory");
|
||||
abort();
|
||||
}
|
||||
client0->displaydpi = 100;
|
||||
client0->rfd = 3;
|
||||
client0->wfd = 4;
|
||||
|
||||
setprocname(argv0);
|
||||
|
||||
@autoreleasepool{
|
||||
|
@ -97,12 +56,10 @@ threadmain(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
callservep9p(void *v)
|
||||
{
|
||||
USED(v);
|
||||
|
||||
servep9p(client0);
|
||||
void
|
||||
rpc_shutdown(void)
|
||||
{
|
||||
[NSApp terminate:myApp];
|
||||
}
|
||||
|
||||
|
@ -128,8 +85,8 @@ callservep9p(void *v)
|
|||
i = [[NSImage alloc] initWithData:d];
|
||||
[NSApp setApplicationIconImage:i];
|
||||
[[NSApp dockTile] display];
|
||||
|
||||
proccreate(callservep9p, nil, 0);
|
||||
|
||||
gfx_started();
|
||||
}
|
||||
|
||||
- (NSApplicationPresentationOptions)window:(id)arg
|
||||
|
@ -242,10 +199,10 @@ callservep9p(void *v)
|
|||
- (BOOL)isFlipped { return YES; }
|
||||
- (BOOL)acceptsFirstResponder { return YES; }
|
||||
|
||||
// rpc_attachscreen allocates a new screen window with the given label and size
|
||||
// rpc_attach allocates a new screen window with the given label and size
|
||||
// and attaches it to client c (by setting c->view).
|
||||
Memimage*
|
||||
rpc_attachscreen(Client *c, char *label, char *winsize)
|
||||
rpc_attach(Client *c, char *label, char *winsize)
|
||||
{
|
||||
LOG(@"attachscreen(%s, %s)", label, winsize);
|
||||
|
||||
|
@ -468,71 +425,73 @@ rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
|
|||
}
|
||||
|
||||
- (void)initimg {
|
||||
@autoreleasepool{
|
||||
CGFloat scale;
|
||||
NSSize size;
|
||||
MTLTextureDescriptor *textureDesc;
|
||||
|
||||
size = [self convertSizeToBacking:[self bounds].size];
|
||||
self.client->mouserect = Rect(0, 0, size.width, size.height);
|
||||
|
||||
LOG(@"initimg %.0f %.0f", size.width, size.height);
|
||||
|
||||
self.img = allocmemimage(self.client->mouserect, XRGB32);
|
||||
if(self.img == nil)
|
||||
panic("allocmemimage: %r");
|
||||
if(self.img->data == nil)
|
||||
panic("img->data == nil");
|
||||
|
||||
textureDesc = [MTLTextureDescriptor
|
||||
texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||
width:size.width
|
||||
height:size.height
|
||||
mipmapped:NO];
|
||||
textureDesc.allowGPUOptimizedContents = YES;
|
||||
textureDesc.usage = MTLTextureUsageShaderRead;
|
||||
textureDesc.cpuCacheMode = MTLCPUCacheModeWriteCombined;
|
||||
self.dlayer.texture = [self.dlayer.device newTextureWithDescriptor:textureDesc];
|
||||
|
||||
scale = [self.win backingScaleFactor];
|
||||
[self.dlayer setDrawableSize:size];
|
||||
[self.dlayer setContentsScale:scale];
|
||||
|
||||
// NOTE: This is not really the display DPI.
|
||||
// On retina, scale is 2; otherwise it is 1.
|
||||
// This formula gives us 220 for retina, 110 otherwise.
|
||||
// That's not quite right but it's close to correct.
|
||||
// https://en.wikipedia.org/wiki/Retina_display#Models
|
||||
self.client->displaydpi = scale * 110;
|
||||
}
|
||||
LOG(@"initimg return");
|
||||
@autoreleasepool {
|
||||
CGFloat scale;
|
||||
NSSize size;
|
||||
MTLTextureDescriptor *textureDesc;
|
||||
|
||||
size = [self convertSizeToBacking:[self bounds].size];
|
||||
self.client->mouserect = Rect(0, 0, size.width, size.height);
|
||||
|
||||
LOG(@"initimg %.0f %.0f", size.width, size.height);
|
||||
|
||||
self.img = allocmemimage(self.client->mouserect, XRGB32);
|
||||
if(self.img == nil)
|
||||
panic("allocmemimage: %r");
|
||||
if(self.img->data == nil)
|
||||
panic("img->data == nil");
|
||||
|
||||
textureDesc = [MTLTextureDescriptor
|
||||
texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||
width:size.width
|
||||
height:size.height
|
||||
mipmapped:NO];
|
||||
textureDesc.allowGPUOptimizedContents = YES;
|
||||
textureDesc.usage = MTLTextureUsageShaderRead;
|
||||
textureDesc.cpuCacheMode = MTLCPUCacheModeWriteCombined;
|
||||
self.dlayer.texture = [self.dlayer.device newTextureWithDescriptor:textureDesc];
|
||||
|
||||
scale = [self.win backingScaleFactor];
|
||||
[self.dlayer setDrawableSize:size];
|
||||
[self.dlayer setContentsScale:scale];
|
||||
|
||||
// NOTE: This is not really the display DPI.
|
||||
// On retina, scale is 2; otherwise it is 1.
|
||||
// This formula gives us 220 for retina, 110 otherwise.
|
||||
// That's not quite right but it's close to correct.
|
||||
// https://en.wikipedia.org/wiki/Retina_display#Models
|
||||
self.client->displaydpi = scale * 110;
|
||||
}
|
||||
}
|
||||
|
||||
// rpc_flushmemscreen flushes changes to view.img's rectangle r
|
||||
// rpc_flush flushes changes to view.img's rectangle r
|
||||
// to the on-screen window, making them visible.
|
||||
// Called from an RPC thread with no client lock held.
|
||||
void
|
||||
rpc_flushmemscreen(Client *client, Rectangle r)
|
||||
rpc_flush(Client *client, Rectangle r)
|
||||
{
|
||||
DrawView *view = (__bridge DrawView*)client->view;
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void){
|
||||
[view flushmemscreen:r];
|
||||
[view flush:r];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)flushmemscreen:(Rectangle)r {
|
||||
LOG(@"flushmemscreen(%d,%d,%d,%d)", r.min.x, r.min.y, Dx(r), Dy(r));
|
||||
if(!rectinrect(r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height))){
|
||||
LOG(@"Rectangle is out of bounds, return.");
|
||||
return;
|
||||
}
|
||||
|
||||
- (void)flush:(Rectangle)r {
|
||||
@autoreleasepool{
|
||||
if(!rectclip(&r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height)) || !rectclip(&r, self.img->r))
|
||||
return;
|
||||
|
||||
// self.client->drawlk protects the pixel data in self.img.
|
||||
// In addition to avoiding a technical data race,
|
||||
// the lock avoids drawing partial updates, which makes
|
||||
// animations like sweeping windows much less flickery.
|
||||
qlock(&self.client->drawlk);
|
||||
[self.dlayer.texture
|
||||
replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r))
|
||||
mipmapLevel:0
|
||||
withBytes:byteaddr(self.img, Pt(r.min.x, r.min.y))
|
||||
bytesPerRow:self.img->width*sizeof(u32int)];
|
||||
qunlock(&self.client->drawlk);
|
||||
|
||||
NSRect nr = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r));
|
||||
dispatch_time_t time;
|
||||
|
@ -565,7 +524,7 @@ rpc_resizeimg(Client *c)
|
|||
|
||||
- (void)resizeimg {
|
||||
[self initimg];
|
||||
_drawreplacescreenimage(self.client, self.img);
|
||||
gfx_replacescreenimage(self.client, self.img);
|
||||
[self sendmouse:0];
|
||||
}
|
||||
|
||||
|
@ -750,7 +709,7 @@ rpc_setmouse(Client *c, Point p)
|
|||
});
|
||||
}
|
||||
|
||||
-(void)setmouse:(Point)p {
|
||||
- (void)setmouse:(Point)p {
|
||||
@autoreleasepool{
|
||||
NSPoint q;
|
||||
|
||||
|
@ -782,21 +741,10 @@ rpc_setmouse(Client *c, Point p)
|
|||
}
|
||||
|
||||
// conforms to protocol NSTextInputClient
|
||||
- (BOOL)hasMarkedText
|
||||
{
|
||||
LOG(@"hasMarkedText");
|
||||
return _markedRange.location != NSNotFound;
|
||||
}
|
||||
- (NSRange)markedRange
|
||||
{
|
||||
LOG(@"markedRange");
|
||||
return _markedRange;
|
||||
}
|
||||
- (NSRange)selectedRange
|
||||
{
|
||||
LOG(@"selectedRange");
|
||||
return _selectedRange;
|
||||
}
|
||||
- (BOOL)hasMarkedText { return _markedRange.location != NSNotFound; }
|
||||
- (NSRange)markedRange { return _markedRange; }
|
||||
- (NSRange)selectedRange { return _selectedRange; }
|
||||
|
||||
- (void)setMarkedText:(id)string
|
||||
selectedRange:(NSRange)sRange
|
||||
replacementRange:(NSRange)rRange
|
||||
|
@ -861,8 +809,8 @@ rpc_setmouse(Client *c, Point p)
|
|||
_markedRange.location, _markedRange.length,
|
||||
_selectedRange.location, _selectedRange.length);
|
||||
}
|
||||
- (void)unmarkText
|
||||
{
|
||||
|
||||
- (void)unmarkText {
|
||||
//NSUInteger i;
|
||||
NSUInteger len;
|
||||
|
||||
|
@ -874,12 +822,13 @@ rpc_setmouse(Client *c, Point p)
|
|||
_markedRange = NSMakeRange(NSNotFound, 0);
|
||||
_selectedRange = NSMakeRange(0, 0);
|
||||
}
|
||||
- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText
|
||||
{
|
||||
|
||||
- (NSArray<NSAttributedStringKey>*)validAttributesForMarkedText {
|
||||
LOG(@"validAttributesForMarkedText");
|
||||
return @[];
|
||||
}
|
||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)r
|
||||
|
||||
- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)r
|
||||
actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
NSRange sr;
|
||||
|
@ -899,9 +848,8 @@ rpc_setmouse(Client *c, Point p)
|
|||
LOG(@" return %@", s);
|
||||
return s;
|
||||
}
|
||||
- (void)insertText:(id)s
|
||||
replacementRange:(NSRange)r
|
||||
{
|
||||
|
||||
- (void)insertText:(id)s replacementRange:(NSRange)r {
|
||||
NSUInteger i;
|
||||
NSUInteger len;
|
||||
|
||||
|
@ -916,22 +864,22 @@ rpc_setmouse(Client *c, Point p)
|
|||
_markedRange = NSMakeRange(NSNotFound, 0);
|
||||
_selectedRange = NSMakeRange(0, 0);
|
||||
}
|
||||
|
||||
- (NSUInteger)characterIndexForPoint:(NSPoint)point
|
||||
{
|
||||
LOG(@"characterIndexForPoint: %g, %g", point.x, point.y);
|
||||
return 0;
|
||||
}
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)r
|
||||
actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)r actualRange:(NSRangePointer)actualRange {
|
||||
LOG(@"firstRectForCharacterRange: (%ld, %ld) (%ld, %ld)",
|
||||
r.location, r.length, actualRange->location, actualRange->length);
|
||||
if(actualRange)
|
||||
*actualRange = r;
|
||||
return [[self window] convertRectToScreen:_lastInputRect];
|
||||
}
|
||||
- (void)doCommandBySelector:(SEL)s
|
||||
{
|
||||
|
||||
- (void)doCommandBySelector:(SEL)s {
|
||||
NSEvent *e;
|
||||
NSEventModifierFlags m;
|
||||
uint c, k;
|
||||
|
@ -955,8 +903,7 @@ rpc_setmouse(Client *c, Point p)
|
|||
}
|
||||
|
||||
// Helper for managing input rect approximately
|
||||
- (void)resetLastInputRect
|
||||
{
|
||||
- (void)resetLastInputRect {
|
||||
LOG(@"resetLastInputRect");
|
||||
_lastInputRect.origin.x = 0.0;
|
||||
_lastInputRect.origin.y = 0.0;
|
||||
|
@ -964,8 +911,7 @@ rpc_setmouse(Client *c, Point p)
|
|||
_lastInputRect.size.height = 0.0;
|
||||
}
|
||||
|
||||
- (void)enlargeLastInputRect:(NSRect)r
|
||||
{
|
||||
- (void)enlargeLastInputRect:(NSRect)r {
|
||||
r.origin.y = [self bounds].size.height - r.origin.y - r.size.height;
|
||||
_lastInputRect = NSUnionRect(_lastInputRect, r);
|
||||
LOG(@"update last input rect (%g, %g, %g, %g)",
|
||||
|
@ -973,8 +919,7 @@ rpc_setmouse(Client *c, Point p)
|
|||
_lastInputRect.size.width, _lastInputRect.size.height);
|
||||
}
|
||||
|
||||
- (void)clearInput
|
||||
{
|
||||
- (void)clearInput {
|
||||
if(_tmpText.length){
|
||||
uint i;
|
||||
int l;
|
||||
|
@ -1079,48 +1024,42 @@ keycvt(uint code)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// rpc_getsnarf reads the current pasteboard as a plain text string.
|
||||
// Called from an RPC thread with no client lock held.
|
||||
char*
|
||||
rpc_getsnarf(void)
|
||||
{
|
||||
NSPasteboard *pb;
|
||||
NSString *s;
|
||||
|
||||
@autoreleasepool{
|
||||
pb = [NSPasteboard generalPasteboard];
|
||||
|
||||
qlock(&snarfl);
|
||||
s = [pb stringForType:NSPasteboardTypeString];
|
||||
qunlock(&snarfl);
|
||||
|
||||
if(s)
|
||||
return strdup((char *)[s UTF8String]);
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
char __block *ret;
|
||||
|
||||
ret = nil;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(void) {
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
NSString *s = [pb stringForType:NSPasteboardTypeString];
|
||||
if(s)
|
||||
ret = strdup((char*)[s UTF8String]);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// rpc_putsnarf writes the given text to the pasteboard.
|
||||
// Called from an RPC thread with no client lock held.
|
||||
void
|
||||
rpc_putsnarf(char *s)
|
||||
{
|
||||
NSArray *t;
|
||||
NSPasteboard *pb;
|
||||
NSString *str;
|
||||
|
||||
if(strlen(s) >= SnarfSize)
|
||||
if(s == nil || strlen(s) >= SnarfSize)
|
||||
return;
|
||||
|
||||
@autoreleasepool{
|
||||
t = [NSArray arrayWithObject:NSPasteboardTypeString];
|
||||
pb = [NSPasteboard generalPasteboard];
|
||||
str = [[NSString alloc] initWithUTF8String:s];
|
||||
|
||||
qlock(&snarfl);
|
||||
[pb declareTypes:t owner:nil];
|
||||
[pb setString:str forType:NSPasteboardTypeString];
|
||||
qunlock(&snarfl);
|
||||
}
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(void) {
|
||||
@autoreleasepool{
|
||||
NSArray *t = [NSArray arrayWithObject:NSPasteboardTypeString];
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
NSString *str = [[NSString alloc] initWithUTF8String:s];
|
||||
[pb declareTypes:t owner:nil];
|
||||
[pb setString:str forType:NSPasteboardTypeString];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -18,18 +18,72 @@ static void runmsg(Client*, Wsysmsg*);
|
|||
static void replymsg(Client*, Wsysmsg*);
|
||||
static void matchkbd(Client*);
|
||||
static void matchmouse(Client*);
|
||||
static void serve(void*);
|
||||
static Client *client0;
|
||||
|
||||
int trace = 0;
|
||||
|
||||
void
|
||||
servep9p(Client *c)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: devdraw (don't run directly)\n");
|
||||
threadexitsall("usage");
|
||||
}
|
||||
|
||||
void
|
||||
threadmain(int argc, char **argv)
|
||||
{
|
||||
/*
|
||||
* Move the protocol off stdin/stdout so that
|
||||
* any inadvertent prints don't screw things up.
|
||||
*/
|
||||
dup(0,3);
|
||||
dup(1,4);
|
||||
close(0);
|
||||
close(1);
|
||||
open("/dev/null", OREAD);
|
||||
open("/dev/null", OWRITE);
|
||||
|
||||
ARGBEGIN{
|
||||
case 'D': /* for good ps -a listings */
|
||||
break;
|
||||
case 'f': /* fall through for backward compatibility */
|
||||
case 'g':
|
||||
case 'b':
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
fmtinstall('W', drawfcallfmt);
|
||||
|
||||
client0 = mallocz(sizeof(Client), 1);
|
||||
if(client0 == nil){
|
||||
fprint(2, "initdraw: allocating client0: out of memory");
|
||||
abort();
|
||||
}
|
||||
client0->displaydpi = 100;
|
||||
client0->rfd = 3;
|
||||
client0->wfd = 4;
|
||||
|
||||
gfx_main();
|
||||
}
|
||||
|
||||
void
|
||||
gfx_started(void)
|
||||
{
|
||||
proccreate(serve, client0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
serve(void *v)
|
||||
{
|
||||
Client *c;
|
||||
uchar buf[4], *mbuf;
|
||||
int nmbuf, n, nn;
|
||||
Wsysmsg m;
|
||||
|
||||
fmtinstall('W', drawfcallfmt);
|
||||
|
||||
c = v;
|
||||
mbuf = nil;
|
||||
nmbuf = 0;
|
||||
while((n = read(c->rfd, buf, 4)) == 4){
|
||||
|
@ -52,6 +106,9 @@ servep9p(Client *c)
|
|||
if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m);
|
||||
runmsg(c, &m);
|
||||
}
|
||||
|
||||
rpc_shutdown();
|
||||
threadexitsall(nil);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -79,13 +136,13 @@ runmsg(Client *c, Wsysmsg *m)
|
|||
switch(m->type){
|
||||
case Tinit:
|
||||
memimageinit();
|
||||
i = rpc_attachscreen(c, m->label, m->winsize);
|
||||
_initdisplaymemimage(c, i);
|
||||
i = rpc_attach(c, m->label, m->winsize);
|
||||
draw_initdisplaymemimage(c, i);
|
||||
replymsg(c, m);
|
||||
break;
|
||||
|
||||
case Trdmouse:
|
||||
qlock(&c->inputlk);
|
||||
qlock(&c->eventlk);
|
||||
c->mousetags.t[c->mousetags.wi++] = m->tag;
|
||||
if(c->mousetags.wi == nelem(c->mousetags.t))
|
||||
c->mousetags.wi = 0;
|
||||
|
@ -93,11 +150,11 @@ runmsg(Client *c, Wsysmsg *m)
|
|||
sysfatal("too many queued mouse reads");
|
||||
c->mouse.stall = 0;
|
||||
matchmouse(c);
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
break;
|
||||
|
||||
case Trdkbd:
|
||||
qlock(&c->inputlk);
|
||||
qlock(&c->eventlk);
|
||||
c->kbdtags.t[c->kbdtags.wi++] = m->tag;
|
||||
if(c->kbdtags.wi == nelem(c->kbdtags.t))
|
||||
c->kbdtags.wi = 0;
|
||||
|
@ -105,7 +162,7 @@ runmsg(Client *c, Wsysmsg *m)
|
|||
sysfatal("too many queued keyboard reads");
|
||||
c->kbd.stall = 0;
|
||||
matchkbd(c);
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
break;
|
||||
|
||||
case Tmoveto:
|
||||
|
@ -148,16 +205,15 @@ runmsg(Client *c, Wsysmsg *m)
|
|||
break;
|
||||
|
||||
case Twrsnarf:
|
||||
putsnarf(m->snarf);
|
||||
rpc_putsnarf(m->snarf);
|
||||
replymsg(c, m);
|
||||
break;
|
||||
|
||||
case Trddraw:
|
||||
qlock(&c->inputlk);
|
||||
n = m->count;
|
||||
if(n > sizeof buf)
|
||||
n = sizeof buf;
|
||||
n = _drawmsgread(c, buf, n);
|
||||
n = draw_dataread(c, buf, n);
|
||||
if(n < 0)
|
||||
replyerror(c, m);
|
||||
else{
|
||||
|
@ -165,16 +221,13 @@ runmsg(Client *c, Wsysmsg *m)
|
|||
m->data = buf;
|
||||
replymsg(c, m);
|
||||
}
|
||||
qunlock(&c->inputlk);
|
||||
break;
|
||||
|
||||
case Twrdraw:
|
||||
qlock(&c->inputlk);
|
||||
if(_drawmsgwrite(c, m->data, m->count) < 0)
|
||||
if(draw_datawrite(c, m->data, m->count) < 0)
|
||||
replyerror(c, m);
|
||||
else
|
||||
replymsg(c, m);
|
||||
qunlock(&c->inputlk);
|
||||
break;
|
||||
|
||||
case Ttop:
|
||||
|
@ -192,13 +245,10 @@ runmsg(Client *c, Wsysmsg *m)
|
|||
/*
|
||||
* Reply to m.
|
||||
*/
|
||||
QLock replylock;
|
||||
static void
|
||||
replymsg(Client *c, Wsysmsg *m)
|
||||
{
|
||||
int n;
|
||||
static uchar *mbuf;
|
||||
static int nmbuf;
|
||||
|
||||
/* T -> R msg */
|
||||
if(m->type%2 == 0)
|
||||
|
@ -208,18 +258,18 @@ replymsg(Client *c, Wsysmsg *m)
|
|||
/* copy to output buffer */
|
||||
n = sizeW2M(m);
|
||||
|
||||
qlock(&replylock);
|
||||
if(n > nmbuf){
|
||||
free(mbuf);
|
||||
mbuf = malloc(n);
|
||||
if(mbuf == nil)
|
||||
qlock(&c->wfdlk);
|
||||
if(n > c->nmbuf){
|
||||
free(c->mbuf);
|
||||
c->mbuf = malloc(n);
|
||||
if(c->mbuf == nil)
|
||||
sysfatal("out of memory");
|
||||
nmbuf = n;
|
||||
c->nmbuf = n;
|
||||
}
|
||||
convW2M(m, mbuf, n);
|
||||
if(write(c->wfd, mbuf, n) != n)
|
||||
convW2M(m, c->mbuf, n);
|
||||
if(write(c->wfd, c->mbuf, n) != n)
|
||||
sysfatal("write: %r");
|
||||
qunlock(&replylock);
|
||||
qunlock(&c->wfdlk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -245,13 +295,13 @@ matchkbd(Client *c)
|
|||
}
|
||||
|
||||
// matchmouse matches queued mouse reads with queued mouse events.
|
||||
// It must be called with c->inputlk held.
|
||||
// It must be called with c->eventlk held.
|
||||
static void
|
||||
matchmouse(Client *c)
|
||||
{
|
||||
Wsysmsg m;
|
||||
|
||||
if(canqlock(&c->inputlk)) {
|
||||
if(canqlock(&c->eventlk)) {
|
||||
fprint(2, "misuse of matchmouse\n");
|
||||
abort();
|
||||
}
|
||||
|
@ -280,7 +330,7 @@ gfx_mousetrack(Client *c, int x, int y, int b, uint ms)
|
|||
{
|
||||
Mouse *m;
|
||||
|
||||
qlock(&c->inputlk);
|
||||
qlock(&c->eventlk);
|
||||
if(x < c->mouserect.min.x)
|
||||
x = c->mouserect.min.x;
|
||||
if(x > c->mouserect.max.x)
|
||||
|
@ -312,15 +362,15 @@ gfx_mousetrack(Client *c, int x, int y, int b, uint ms)
|
|||
}
|
||||
matchmouse(c);
|
||||
}
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
}
|
||||
|
||||
// kputc adds ch to the keyboard buffer.
|
||||
// It must be called with c->inputlk held.
|
||||
// It must be called with c->eventlk held.
|
||||
static void
|
||||
kputc(Client *c, int ch)
|
||||
{
|
||||
if(canqlock(&c->inputlk)) {
|
||||
if(canqlock(&c->eventlk)) {
|
||||
fprint(2, "misuse of kputc\n");
|
||||
abort();
|
||||
}
|
||||
|
@ -339,12 +389,12 @@ kputc(Client *c, int ch)
|
|||
void
|
||||
gfx_abortcompose(Client *c)
|
||||
{
|
||||
qlock(&c->inputlk);
|
||||
qlock(&c->eventlk);
|
||||
if(c->kbd.alting) {
|
||||
c->kbd.alting = 0;
|
||||
c->kbd.nk = 0;
|
||||
}
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
}
|
||||
|
||||
// gfx_keystroke records a single-rune keystroke.
|
||||
|
@ -354,11 +404,11 @@ gfx_keystroke(Client *c, int ch)
|
|||
{
|
||||
int i;
|
||||
|
||||
qlock(&c->inputlk);
|
||||
qlock(&c->eventlk);
|
||||
if(ch == Kalt){
|
||||
c->kbd.alting = !c->kbd.alting;
|
||||
c->kbd.nk = 0;
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
return;
|
||||
}
|
||||
if(ch == Kcmd+'r') {
|
||||
|
@ -368,24 +418,24 @@ gfx_keystroke(Client *c, int ch)
|
|||
c->forcedpi = 100;
|
||||
else
|
||||
c->forcedpi = 225;
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
rpc_resizeimg(c);
|
||||
return;
|
||||
}
|
||||
if(!c->kbd.alting){
|
||||
kputc(c, ch);
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
return;
|
||||
}
|
||||
if(c->kbd.nk >= nelem(c->kbd.k)) // should not happen
|
||||
c->kbd.nk = 0;
|
||||
c->kbd.k[c->kbd.nk++] = ch;
|
||||
ch = _latin1(c->kbd.k, c->kbd.nk);
|
||||
ch = latin1(c->kbd.k, c->kbd.nk);
|
||||
if(ch > 0){
|
||||
c->kbd.alting = 0;
|
||||
kputc(c, ch);
|
||||
c->kbd.nk = 0;
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
return;
|
||||
}
|
||||
if(ch == -1){
|
||||
|
@ -393,10 +443,10 @@ gfx_keystroke(Client *c, int ch)
|
|||
for(i=0; i<c->kbd.nk; i++)
|
||||
kputc(c, c->kbd.k[i]);
|
||||
c->kbd.nk = 0;
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
return;
|
||||
}
|
||||
// need more input
|
||||
qunlock(&c->inputlk);
|
||||
qunlock(&c->eventlk);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -733,6 +733,6 @@ _xreplacescreenimage(void)
|
|||
XFreePixmap(_x.display, _x.nextscreenpm);
|
||||
_x.nextscreenpm = pixmap;
|
||||
_x.screenr = r;
|
||||
_drawreplacescreenimage(m);
|
||||
gfx_replacescreenimage(m);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ abortcompose(void)
|
|||
|
||||
static Rune* sendrune(Rune);
|
||||
|
||||
extern int _latin1(Rune*, int);
|
||||
extern int latin1(Rune*, int);
|
||||
static Rune*
|
||||
xtoplan9latin1(XEvent *e)
|
||||
{
|
||||
|
@ -182,7 +182,7 @@ sendrune(Rune r)
|
|||
return nil;
|
||||
}
|
||||
k[nk++] = r;
|
||||
n = _latin1(k, nk);
|
||||
n = latin1(k, nk);
|
||||
if(n > 0){
|
||||
alting = 0;
|
||||
k[0] = n;
|
||||
|
|
|
@ -365,7 +365,7 @@ runmsg(Wsysmsg *m)
|
|||
n = m->count;
|
||||
if(n > sizeof buf)
|
||||
n = sizeof buf;
|
||||
n = _drawmsgread(buf, n);
|
||||
n = draw_dataread(buf, n);
|
||||
if(n < 0)
|
||||
replyerror(m);
|
||||
else{
|
||||
|
@ -376,7 +376,7 @@ runmsg(Wsysmsg *m)
|
|||
break;
|
||||
|
||||
case Twrdraw:
|
||||
if(_drawmsgwrite(m->data, m->count) < 0)
|
||||
if(draw_datawrite(m->data, m->count) < 0)
|
||||
replyerror(m);
|
||||
else
|
||||
replymsg(m);
|
||||
|
|
Loading…
Reference in a new issue