Cleanup drag&drop, bar.c.

This commit is contained in:
Kris Maglione 2008-01-21 17:28:23 -05:00
parent 7b1c1664f9
commit 2999577155
7 changed files with 210 additions and 166 deletions

View File

@ -8,6 +8,10 @@
static Handlers handlers;
static Bar *free_bars;
#define foreach_bar(s, b) \
for(int __bar_n=0; __bar_n < nelem((s)->bar); __bar_n++) \
for((b)=(s)->bar[__bar_n]; (b); (b)=(b)->next)
void
bar_init(WMScreen *s) {
WinAttr wa;
@ -29,6 +33,8 @@ bar_init(WMScreen *s) {
CWOverrideRedirect
| CWBackPixmap
| CWEventMask);
s->barwin->aux = s;
xdnd_initwindow(s->barwin);
sethandler(s->barwin, &handlers);
mapwin(s->barwin);
}
@ -36,7 +42,9 @@ bar_init(WMScreen *s) {
Bar*
bar_create(Bar **bp, const char *name) {
static uint id = 1;
WMScreen *s;
Bar *b;
uint i;
b = bar_find(*bp, name);;
if(b)
@ -59,6 +67,13 @@ bar_create(Bar **bp, const char *name) {
break;
b->next = *bp;
*bp = b;
/* FIXME: Kludge. */
for(s=screens; s < screens+num_screens; s++) {
i = bp - s->bar;
if(i < nelem(s->bar))
b->bar = i;
}
return b;
}
@ -95,33 +110,30 @@ bar_draw(WMScreen *s) {
Bar *b, *tb, *largest, **pb;
Rectangle r;
Align align;
uint width, tw, nb;
uint width, tw;
float shrink;
largest = nil;
tw = width = 0;
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; b=b->next) {
b->r.min = ZP;
b->r.max.y = Dy(s->brect);
b->r.max.x = def.font->height & ~1;
if(b->text && strlen(b->text))
b->r.max.x += textwidth(def.font, b->text);
width += Dx(b->r);
}
foreach_bar(s, b) {
b->r.min = ZP;
b->r.max.y = Dy(s->brect);
b->r.max.x = def.font->height & ~1;
if(b->text && strlen(b->text))
b->r.max.x += textwidth(def.font, b->text);
width += Dx(b->r);
}
if(width > Dx(s->brect)) { /* Not enough room. Shrink bars until they all fit. */
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; b=b->next) {
for(pb = &largest; *pb; pb = &pb[0]->smaller)
if(Dx(pb[0]->r) < Dx(b->r))
break;
b->smaller = *pb;
*pb = b;
}
foreach_bar(s, b) {
for(pb=&largest; *pb; pb=&pb[0]->smaller)
if(Dx(pb[0]->r) < Dx(b->r))
break;
b->smaller = *pb;
*pb = b;
}
SET(shrink);
for(tb = largest; tb; tb = tb->smaller) {
for(tb=largest; tb; tb=tb->smaller) {
width -= Dx(tb->r);
tw += Dx(tb->r);
shrink = (Dx(s->brect) - width) / (float)tw;
@ -130,32 +142,30 @@ bar_draw(WMScreen *s) {
break;
}
if(tb)
for(b = largest; b != tb->smaller; b = b->smaller)
for(b=largest; b != tb->smaller; b=b->smaller)
b->r.max.x *= shrink;
width += tw * shrink;
}
tb = nil;
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; tb=b, b=b->next) {
if(b == s->bar[BarRight])
b->r.max.x += Dx(s->brect) - width;
if(tb)
b->r = rectaddpt(b->r, Pt(tb->r.max.x, 0));
}
foreach_bar(s, b) {
if(tb)
b->r = rectaddpt(b->r, Pt(tb->r.max.x, 0));
if(b == s->bar[BarRight])
b->r.max.x += Dx(s->brect) - width;
tb = b;
}
r = rectsubpt(s->brect, s->brect.min);
fill(screen->ibuf, r, def.normcolor.bg);
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; b=b->next) {
align = Center;
if(b == s->bar[BarRight])
align = East;
fill(screen->ibuf, b->r, b->col.bg);
drawstring(screen->ibuf, def.font, b->r, align, b->text, b->col.fg);
border(screen->ibuf, b->r, 1, b->col.border);
}
foreach_bar(s, b) {
align = Center;
if(b == s->bar[BarRight])
align = East;
fill(screen->ibuf, b->r, b->col.bg);
drawstring(screen->ibuf, def.font, b->r, align, b->text, b->col.fg);
border(screen->ibuf, b->r, 1, b->col.border);
}
copyimage(s->barwin, r, screen->ibuf, ZP);
sync();
}
@ -170,44 +180,59 @@ bar_find(Bar *bp, const char *name) {
return b;
}
static char *barside[] = {
[BarLeft] = "Left",
[BarRight] = "Right",
};
static Bar*
findbar(WMScreen *s, Point p) {
Bar *b;
foreach_bar(s, b)
if(rect_haspoint_p(p, b->r))
return b;
return nil;
}
static void
bdown_event(Window *w, XButtonPressedEvent *e) {
WMScreen *s;
Bar *b;
USED(w);
/* Ungrab so a menu can receive events before the button is released */
XUngrabPointer(display, e->time);
sync();
for(b=screen->bar[BarLeft]; b; b=b->next)
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("LeftBarMouseDown %d %s\n", e->button, b->name);
return;
}
for(b=screen->bar[BarRight]; b; b=b->next)
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("RightBarMouseDown %d %s\n", e->button, b->name);
return;
}
s = w->aux;
b = findbar(s, Pt(e->x, e->y));
if(b)
event("%sBarMouseDown %d %s\n", barside[b->bar], e->button, b->name);
}
static void
bup_event(Window *w, XButtonPressedEvent *e) {
WMScreen *s;
Bar *b;
USED(w, e);
s = w->aux;
b = findbar(s, Pt(e->x, e->y));
if(b)
event("%sBarClick %d %s\n", barside[b->bar], e->button, b->name);
}
for(b=screen->bar[BarLeft]; b; b=b->next)
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("LeftBarClick %d %s\n", e->button, b->name);
return;
}
for(b=screen->bar[BarRight]; b; b=b->next)
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("RightBarClick %d %s\n", e->button, b->name);
return;
}
static Rectangle
dndmotion_event(Window *w, Point p) {
WMScreen *s;
Bar *b;
s = w->aux;
b = findbar(s, p);
if(b) {
event("%sBarDND 1 %s\n", barside[b->bar], b->name);
return b->r;
}
return ZR;
}
static void
@ -219,5 +244,6 @@ expose_event(Window *w, XExposeEvent *e) {
static Handlers handlers = {
.bdown = bdown_event,
.bup = bup_event,
.dndmotion = dndmotion_event,
.expose = expose_event,
};

View File

@ -117,6 +117,7 @@ struct Bar {
char buf[280];
char text[256];
char name[256];
int bar;
ushort id;
Rectangle r;
CTuple col;

View File

@ -126,8 +126,8 @@ float_placeframe(Frame *f) {
p = ZP; /* SET(p) */
if(vp->n == 0) {
p.x = random() % max(0, Dx(a->r) - dim.x);
p.y = random() % max(0, Dy(a->r) - dim.y);
p.x = random() % max(1, Dx(a->r) - dim.x);
p.y = random() % max(1, Dy(a->r) - dim.y);
}else {
area = LONG_MAX;
for(i=0; i < vp->n; i++) {

View File

@ -211,7 +211,7 @@ char* toutf8n(const char*, size_t);
/* xdnd.c */
int xdnd_clientmessage(XClientMessageEvent*);
void xdnd_init(void);
void xdnd_initwindow(Window*);
/* xext.c */
void randr_event(XEvent*);

View File

@ -465,7 +465,6 @@ main(int argc, char *argv[]) {
| CWCursor);
bar_init(s);
}
xdnd_init();
screen->focus = nil;
setfocus(screen->barwin, RevertToParent);

View File

@ -5,23 +5,30 @@
#include "fns.h"
void
xdnd_init(void) {
xdnd_initwindow(Window *w) {
long l;
l = 3; /* They are insane. Why is this an ATOM?! */
changeprop_long(screen->barwin, "XdndAware", "ATOM", &l, 1);
changeprop_long(w, "XdndAware", "ATOM", &l, 1);
}
typedef struct Dnd Dnd;
struct Dnd {
XWindow source;
Rectangle r;
};
int
xdnd_clientmessage(XClientMessageEvent *e) {
static Bar *oldbar;
Window *w;
Dnd *dnd;
long *l;
Rectangle r;
Point p;
long *l;
Bar *b;
long pos, siz;
int msg;
dnd = nil;
msg = e->message_type;
l = e->data.l;
Dprint(DDnd, "ClientMessage: %A\n", msg);
@ -29,45 +36,49 @@ xdnd_clientmessage(XClientMessageEvent *e) {
if(msg == xatom("XdndEnter")) {
if(e->format != 32)
return -1;
oldbar = nil;
w = findwin(e->window);
if(w) {
if(w->dnd == nil)
w->dnd = emallocz(sizeof *dnd);
dnd = w->dnd;
dnd->source = l[0];
dnd->r = ZR;
}
return 1;
}else
if(msg == xatom("XdndLeave")) {
if(e->format != 32)
return -1;
oldbar = nil;
w = findwin(e->window);
if(w && w->dnd) {
free(w->dnd);
w->dnd = nil;
}
return 1;
}else
if(msg == xatom("XdndPosition")) {
if(e->format != 32)
return -1;
p.x = (ulong)l[2] >> 16;
p.y = (ulong)l[2] & 0xffff;
p = subpt(p, screen->barwin->r.min);
Dprint(DDnd, "\tp: %P\n", p);
/* XXX: This should be done in bar.c. */
for(b=screen->bar[BarLeft]; b; b=b->next)
if(rect_haspoint_p(p, b->r)) {
if(b != oldbar)
event("LeftBarDND 1 %s\n", b->name);
break;
}
if(b == nil)
for(b=screen->bar[BarRight]; b; b=b->next)
if(rect_haspoint_p(p, b->r)) {
if(b != oldbar)
event("RightBarDND 1 %s\n", b->name);
break;
}
pos = 0;
siz = 0;
oldbar = b;
if(b) {
r = rectaddpt(b->r, screen->barwin->r.min);
r = ZR;
w = findwin(e->window);
if(w)
dnd = w->dnd;
if(dnd) {
p.x = (ulong)l[2] >> 16;
p.y = (ulong)l[2] & 0xffff;
p = subpt(p, w->r.min);
Dprint(DDnd, "\tw: %W\n", w);
Dprint(DDnd, "\tp: %P\n", p);
if(eqrect(dnd->r, ZR) || !rect_haspoint_p(p, dnd->r))
if(w->handler->dndmotion)
dnd->r = w->handler->dndmotion(w, p);
r = dnd->r;
if(!eqrect(r, ZR))
r = rectaddpt(r, w->r.min);
Dprint(DDnd, "\tr: %R\n", r);
pos = (r.min.x<<16) | r.min.y;
siz = (Dx(r)<<16) | Dy(r);
}
pos = (r.min.x<<16) | r.min.y;
siz = (Dx(r)<<16) | Dy(r);
sendmessage(window(l[0]), "XdndStatus", e->window, 0, pos, siz, 0);
return 1;
}

View File

@ -27,26 +27,17 @@ enum Align {
Center = NEast | SWest,
};
enum WindowType {
WWindow,
WImage,
};
typedef enum Align Align;
typedef struct CTuple CTuple;
typedef struct Point Point;
typedef struct Rectangle Rectangle;
typedef struct Screen Screen;
typedef struct Ewmh Ewmh;
typedef struct Window Window;
typedef struct WinHints WinHints;
typedef struct Handlers Handlers;
typedef struct Window Image;
typedef struct Font Font;
typedef XSetWindowAttributes WinAttr;
struct CTuple {
ulong bg;
ulong fg;
ulong border;
char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
};
typedef struct Point Point;
typedef struct Rectangle Rectangle;
struct Point {
int x, y;
@ -56,27 +47,54 @@ struct Rectangle {
Point min, max;
};
typedef struct CTuple CTuple;
typedef struct Ewmh Ewmh;
typedef struct Font Font;
typedef struct Handlers Handlers;
typedef struct Screen Screen;
typedef struct WinHints WinHints;
typedef struct Window Image;
typedef struct Window Window;
struct CTuple {
ulong bg;
ulong fg;
ulong border;
char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
};
struct Ewmh {
long type;
long ping;
long timer;
};
struct Window {
int type;
XWindow w;
Window *parent;
Drawable image;
GC gc;
Rectangle r;
void *aux;
Handlers *handler;
Window *next, *prev;
WinHints *hints;
Ewmh ewmh;
bool mapped;
int unmapped;
int depth;
struct Font {
XFontStruct *xfont;
XFontSet set;
int ascent;
int descent;
uint height;
char *name;
};
struct Handlers {
Rectangle (*dndmotion)(Window*, Point);
void (*bdown)(Window*, XButtonEvent*);
void (*bup)(Window*, XButtonEvent*);
void (*configreq)(Window*, XConfigureRequestEvent*);
void (*destroy)(Window*, XDestroyWindowEvent*);
void (*enter)(Window*, XCrossingEvent*);
void (*expose)(Window*, XExposeEvent*);
void (*focusin)(Window*, XFocusChangeEvent*);
void (*focusout)(Window*, XFocusChangeEvent*);
void (*kdown)(Window*, XKeyEvent*);
void (*kup)(Window*, XKeyEvent*);
void (*leave)(Window*, XCrossingEvent*);
void (*map)(Window*, XMapEvent*);
void (*motion)(Window*, XMotionEvent*);
void (*property)(Window*, XPropertyEvent*);
void (*unmap)(Window*, XUnmapEvent*);
};
struct WinHints {
@ -92,45 +110,36 @@ struct WinHints {
bool position;
};
struct Handlers {
void (*bdown)(Window*, XButtonEvent*);
void (*bup)(Window*, XButtonEvent*);
void (*kdown)(Window*, XKeyEvent*);
void (*kup)(Window*, XKeyEvent*);
void (*focusin)(Window*, XFocusChangeEvent*);
void (*focusout)(Window*, XFocusChangeEvent*);
void (*enter)(Window*, XCrossingEvent*);
void (*leave)(Window*, XCrossingEvent*);
void (*motion)(Window*, XMotionEvent*);
void (*destroy)(Window*, XDestroyWindowEvent*);
void (*configreq)(Window*, XConfigureRequestEvent*);
void (*map)(Window*, XMapEvent*);
void (*unmap)(Window*, XUnmapEvent*);
void (*property)(Window*, XPropertyEvent*);
void (*expose)(Window*, XExposeEvent*);
struct Window {
int type;
XWindow w;
Drawable image;
GC gc;
Rectangle r;
Window* parent;
Window* next;
Window* prev;
Handlers* handler;
WinHints* hints;
Ewmh ewmh;
void* dnd;
void* aux;
bool mapped;
int unmapped;
int depth;
};
struct Screen {
int screen;
Window root;
Colormap colormap;
Visual *visual;
Rectangle rect;
GC gc;
int depth;
int fd;
ulong black, white;
};
enum { WWindow, WImage };
struct Font {
XFontStruct *xfont;
XFontSet set;
int ascent;
int descent;
uint height;
char *name;
int screen;
Window root;
GC gc;
Colormap colormap;
Visual* visual;
Rectangle rect;
int depth;
int fd;
ulong black;
ulong white;
};
#ifdef VARARGCK
@ -147,8 +156,6 @@ extern Point ZP;
extern Rectangle ZR;
extern Window* pointerwin;
Rectangle insetrect(Rectangle r, int n);
Point Pt(int x, int y);
Rectangle Rect(int x0, int y0, int x1, int y1);
Rectangle Rpt(Point min, Point max);