ref: abb04b10b904fc3937ac0b790f0dc850ae7acde1
parent: dafdfcb12496bfc27cdc863996172a7409dffd11
author: aap <aap@papnet.eu>
date: Mon Jan 30 14:14:41 EST 2023
border resize/move; fixes; cleanup
--- a/TODO
+++ b/TODO
@@ -1,10 +1,10 @@
rethink resizing and repainting
rethink hiding/unhiding
snarfversion
-check for bad rects
-border resize/move
+check for bad rects (what's left here?)
top/bottom/current seems to work a bit different in rio
release keys and buttons when unfocused
+make sure there are no deadlocks
...
ideas:
--- a/inc.h
+++ b/inc.h
@@ -94,7 +94,16 @@
NumColors
};
+extern Image *background;
extern Image *colors[NumColors];
+extern Cursor whitearrow;
+extern Cursor query;
+extern Cursor crosscursor;
+extern Cursor boxcursor;
+extern Cursor sightcursor;
+extern Cursor *corners[9];
+void initdata(void);
+
extern Screen *wscreen;
extern Mousectl *mctl;
extern int scrolling;
@@ -103,12 +112,14 @@
extern int gotscreen;
extern int servekbd;
-extern Cursor whitearrow;
extern Cursor *cursor;
void setcursoroverride(Cursor *c, int ov);
void setcursornormal(Cursor *c);
+Rectangle newrect(void);
+int goodrect(Rectangle r);
+
typedef struct RuneConvBuf RuneConvBuf;
struct RuneConvBuf
{
@@ -215,6 +226,8 @@
Channel *mouseread;
Channel *wctlread;
Channel *complete;
+
+ char *threadname; /* for debugging */
};
extern Window *bottomwin, *topwin;
@@ -235,10 +248,12 @@
void wsetlabel(Window *w, char *label);
void wsetname(Window *w);
void wsetpid(Window *w, int pid, int dolabel);
+void wdelete(Window *w);
void wmove(Window *w, Point pos);
void wraise(Window *w);
void wlower(Window *w);
void wfocus(Window *w);
+void wunfocus(Window *w);
int whide(Window *w);
int wunhide(Window *w);
void wsethold(Window *w, int hold);
@@ -274,8 +289,6 @@
extern Channel *totap; /* our keyboard input to tap program */
extern Channel *wintap; /* tell the tapthread which Window to send to */
-
-Rectangle newrect(void);
extern Srv fsys;
void fs(void);
--- a/main.c
+++ b/main.c
@@ -1,65 +1,5 @@
#include "inc.h"
-Cursor whitearrow = {
- {0, 0},
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
- 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC,
- 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
- 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
- {0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C,
- 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C,
- 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C,
- 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
-};
-
-Cursor query = {
- {-7,-7},
- {0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe,
- 0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8,
- 0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0,
- 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },
- {0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c,
- 0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0,
- 0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80,
- 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
-};
-
-Cursor crosscursor = {
- {-7, -7},
- {0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
- 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0,
- 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, },
- {0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
- 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE,
- 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
- 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, }
-};
-
-Cursor boxcursor = {
- {-7, -7},
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
- 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
- {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
- 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
- 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
- 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, }
-};
-
-Cursor sightcursor = {
- {-7, -7},
- {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
- 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
- 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, },
- {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
- 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
- 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
- 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00, }
-};
-
typedef struct RKeyboardctl RKeyboardctl;
struct RKeyboardctl
{
@@ -75,8 +15,6 @@
int gotscreen;
int servekbd;
-Image *background;
-Image *colors[NumColors];
Screen *wscreen;
void
@@ -284,6 +222,78 @@
return rc;
}
+int
+whichside(int x, int lo, int hi)
+{
+ return x < lo+20 ? 0 :
+ x > hi-20 ? 2 :
+ 1;
+}
+
+/* 0 1 2
+ * 3 5
+ * 6 7 8 */
+int
+whichcorner(Rectangle r, Point p)
+{
+ int i, j;
+
+ i = whichside(p.x, r.min.x, r.max.x);
+ j = whichside(p.y, r.min.y, r.max.y);
+ return 3*j+i;
+}
+
+/* replace corner or edge of rect with point */
+Rectangle
+changerect(Rectangle r, int corner, Point p)
+{
+ switch(corner){
+ case 0: return Rect(p.x, p.y, r.max.x, r.max.y);
+ case 1: return Rect(r.min.x, p.y, r.max.x, r.max.y);
+ case 2: return Rect(r.min.x, p.y, p.x+1, r.max.y);
+ case 3: return Rect(p.x, r.min.y, r.max.x, r.max.y);
+ case 5: return Rect(r.min.x, r.min.y, p.x+1, r.max.y);
+ case 6: return Rect(p.x, r.min.y, r.max.x, p.y+1);
+ case 7: return Rect(r.min.x, r.min.y, r.max.x, p.y+1);
+ case 8: return Rect(r.min.x, r.min.y, p.x+1, p.y+1);
+ }
+ return r;
+}
+
+Rectangle
+bandrect(Rectangle r, int but, Mousectl *mc)
+{
+ Rectangle or, nr;
+ int corner, ncorner;
+
+ or = r;
+ corner = whichcorner(r, mc->xy);
+ setcursornormal(corners[corner]);
+
+ do{
+ drawgetrect(r, 1);
+ readmouse(mc);
+ drawgetrect(r, 0);
+ nr = canonrect(changerect(r, corner, mc->xy));
+ if(goodrect(nr))
+ r = nr;
+ ncorner = whichcorner(r, mc->xy);
+ /* can switch from edge to corner, but not vice versa */
+ if(ncorner != corner && ncorner != 4 && (corner|~ncorner) & 1){
+ corner = ncorner;
+ setcursornormal(corners[corner]);
+ }
+ }while(mc->buttons == but);
+
+ if(mc->buttons){
+ drainmouse(mctl, nil);
+ return or;
+ }
+
+ setcursornormal(nil);
+ return r;
+}
+
Window*
pick(void)
{
@@ -299,10 +309,11 @@
}
void
-grab(void)
+grab(Window *w)
{
- Window *w = clickwindow(3, mctl);
if(w == nil)
+ w = clickwindow(3, mctl);
+ if(w == nil)
setcursoroverride(nil, FALSE);
else{
Rectangle r = dragrect(3, w->img->r, mctl);
@@ -330,6 +341,17 @@
}
}
+void
+bandresize(Window *w)
+{
+ Rectangle r;
+ r = bandrect(w->img->r, mctl->buttons, mctl);
+ if(!eqrect(r, w->img->r)){
+ wresize(w, r);
+ flushimage(display, 1);
+ }
+}
+
int
obscured(Window *w, Rectangle r, Window *t)
{
@@ -357,6 +379,51 @@
return 0;
}
+/* Check that newly created window will be of manageable size */
+int
+goodrect(Rectangle r)
+{
+ if(badrect(r) || !eqrect(canonrect(r), r))
+ return 0;
+ /* reasonable sizes only please */
+ if(Dx(r) > BIG*Dx(screen->r))
+ return 0;
+ if(Dy(r) > BIG*Dy(screen->r))
+ return 0;
+ /*
+ * the height has to be big enough to fit one line of text.
+ * that includes the border on each side with an extra pixel
+ * so that the text is still drawn
+ */
+ if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height)
+ return 0;
+ /* window must be on screen */
+ if(!rectXrect(screen->r, r))
+ return 0;
+ /* must have some screen and border visible so we can move it out of the way */
+ if(rectinrect(screen->r, insetrect(r, Borderwidth)))
+ return 0;
+ return 1;
+}
+
+/* Rectangle for new window */
+Rectangle
+newrect(void)
+{
+ static int i = 0;
+ int minx, miny, dx, dy;
+
+ dx = min(600, Dx(screen->r) - 2*Borderwidth);
+ dy = min(400, Dy(screen->r) - 2*Borderwidth);
+ minx = 32 + 16*i;
+ miny = 32 + 16*i;
+ i++;
+ i %= 10;
+
+ return Rect(minx, miny, minx+dx, miny+dy);
+}
+
+
enum {
Cut,
Paste,
@@ -471,11 +538,11 @@
if(w) sweep(w);
break;
case Move:
- grab();
+ grab(nil);
break;
case Delete:
w = pick();
- if(w) wsendmsg(w, Deleted);
+ if(w) wdelete(w);
break;
case Hide:
w = pick();
@@ -502,51 +569,55 @@
mthread(void*)
{
Window *w;
- int inside;
threadsetname("mousethread");
while(readmouse(mctl) != -1){
w = wpointto(mctl->xy);
+ cursorwin = w;
again:
- inside = w && w == focused && ptinrect(mctl->xy, w->contrect);
- cursorwin = w;
- if(w)
- wsetcursor(w);
- else
+ if(w == nil){
setcursornormal(nil);
-
-/* TODO: handle borders */
- if(inside && w->mouseopen){
- drainmouse(mctl, w->mc.c);
- }else if(inside){
-// TODO: this can't happen with rio, but maybe we should support it
-if(mctl->buttons && topwin != w)
-wraise(w);
- if(mctl->buttons & (1|8|16) || ptinrect(mctl->xy, w->text.scrollr))
- drainmouse(mctl, w->mc.c);
- if(mctl->buttons & 2){
- incref(w);
- btn2menu(w);
- wrelease(w);
- }
if(mctl->buttons & 4)
btn3menu();
- }else if(w){
+ }else if(!ptinrect(mctl->xy, w->contrect)){
+ /* border */
+ setcursornormal(corners[whichcorner(w->img->r, mctl->xy)]);
+ if(mctl->buttons & 7){
+ wraise(w);
+ wfocus(w);
+ if(mctl->buttons & 4)
+ grab(w);
+ if(mctl->buttons & 3)
+ bandresize(w);
+ }
+ }else if(w != focused){
+ wsetcursor(w);
if(mctl->buttons & 7 ||
mctl->buttons & (8|16) && focused->mouseopen){
wraise(w);
wfocus(w);
- if(ptinrect(mctl->xy, w->contrect)){ // temp hack for borders
if(mctl->buttons & 1)
drainmouse(mctl, nil);
else
goto again;
- }
}
- }else{
+ }else if(!w->mouseopen){
+ wsetcursor(w);
+ if(mctl->buttons && topwin != w)
+ wraise(w);
+ if(mctl->buttons & (1|8|16) || ptinrect(mctl->xy, w->text.scrollr))
+ drainmouse(mctl, w->mc.c);
+ if(mctl->buttons & 2){
+ incref(w);
+ btn2menu(w);
+ wrelease(w);
+ }
if(mctl->buttons & 4)
btn3menu();
+ }else{
+ wsetcursor(w);
+ drainmouse(mctl, w->mc.c);
}
}
}
@@ -737,7 +808,6 @@
return nil;
}
-/* BUG: there's a deadlock somewhere sometimes when you delete a ktrans window */
void
keyboardtap(void*)
{
@@ -874,21 +944,7 @@
snarffd = open("/dev/snarf", OREAD|OCEXEC);
gotscreen = access("/dev/screen", AEXIST)==0;
- background = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
- colors[BACK] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xFFFFFFFF);
- colors[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCFF);
- colors[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x999999FF);
- colors[TEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF);
- colors[HTEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF);
-
- colors[TITLE] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreygreen);
- colors[LTITLE] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen);
- colors[TITLEHOLD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue);
- colors[LTITLEHOLD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreyblue);
-
- colors[PALETEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x666666FF);
- colors[HOLDTEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue);
- colors[PALEHOLDTEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreyblue);
+ initdata();
wscreen = allocscreen(screen, background, 0);
draw(screen, screen->r, background, nil, ZP);
--- a/mkfile
+++ b/mkfile
@@ -8,7 +8,8 @@
wctl.$O \
fs.$O \
util.$O \
- time.$O
+ time.$O \
+ data.$O
HFILES=inc.h
--- a/wind.c
+++ b/wind.c
@@ -165,8 +165,7 @@
if(w->deleted)
return;
w->deleted = TRUE;
- if(focused == w)
- wfocus(nil);
+ assert(w != focused); /* this must be done elsewhere */
wlistremove(w);
for(i = 0; i < nwindows; i++)
if(windows[i] == w){
@@ -174,7 +173,6 @@
memmove(&windows[i], &windows[i+1], (nwindows-i)*sizeof(Window*));
break;
}
-
if(w->img){
/* rio does this, not sure if useful */
originwindow(w->img, w->img->r.min, screen->r.max);
@@ -194,6 +192,7 @@
return 0;
if(i < 0)
panic("negative ref count");
+ wunfocus(w);
wclose(w);
wsendmsg(w, Closed);
return 1;
@@ -202,6 +201,7 @@
void
wsendmsg(Window *w, int type)
{
+ assert(w->threadname != threadgetname());
sendul(w->ctl, type);
}
@@ -283,6 +283,13 @@
}
void
+wdelete(Window *w)
+{
+ wunfocus(w);
+ wsendmsg(w, Deleted);
+}
+
+void
wrepaint(Window *w)
{
wsetcolors(w);
@@ -362,7 +369,7 @@
prev = focused;
focused = w;
sendp(wintap, w);
- /* TODO a bit ugly the repitition,
+ /* TODO a bit ugly the repetition,
* but this might not stay anyways */
if(prev){
prev->wctlready = TRUE;
@@ -376,6 +383,13 @@
}
}
+void
+wunfocus(Window *w)
+{
+ if(w == focused)
+ wfocus(nil);
+}
+
int
whide(Window *w)
{
@@ -382,8 +396,7 @@
if(w->hidden)
return -1;
incref(w);
- if(w == focused)
- wfocus(nil);
+ wunfocus(w);
w->hidden = TRUE;
w->wctlready = TRUE;
originwindow(w->img, w->img->r.min, screen->r.max);
@@ -777,6 +790,7 @@
w = arg;
threadsetname("winthread-%d", w->id);
+ w->threadname = threadgetname();
x = &w->text;
nr = 0;
memset(&cnv, 0, sizeof(cnv));
@@ -1030,7 +1044,7 @@
pid = recvul(cpid);
chanfree(cpid);
if(pid == 0){
- wsendmsg(w, Deleted);
+ wdelete(w);
return 0;
}
}