mirror of
https://github.com/amiwm/amiwm.git
synced 2026-03-23 17:19:14 +00:00
This reverts commitb9e7c7313d, reversing changes made to774f98ef87. It broke ToolItem input; will need to dig into this a bit more.
763 lines
23 KiB
C
763 lines
23 KiB
C
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xresource.h>
|
|
#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
|
|
#include <X11/extensions/shape.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "drawinfo.h"
|
|
#include "screen.h"
|
|
#include "icon.h"
|
|
#include "client.h"
|
|
#include "icc.h"
|
|
#include "prefs.h"
|
|
#include "module.h"
|
|
#include "libami.h"
|
|
|
|
#ifdef AMIGAOS
|
|
#include <pragmas/xlib_pragmas.h>
|
|
extern struct Library *XLibBase;
|
|
#endif
|
|
|
|
#define mx(a,b) ((a)>(b)?(a):(b))
|
|
|
|
extern Display *dpy;
|
|
extern XContext client_context, screen_context;
|
|
extern Cursor wm_curs;
|
|
extern int shape_extn;
|
|
extern void redrawmenubar(Scrn *, Window);
|
|
void reshape_frame(Client *c);
|
|
|
|
Window creategadget(Client *c, Window p, int x, int y, int w, int h)
|
|
{
|
|
XSetWindowAttributes attr;
|
|
Window r;
|
|
|
|
attr.override_redirect=True;
|
|
attr.background_pixel=scr->dri.dri_Pens[BACKGROUNDPEN];
|
|
r=XCreateWindow(dpy, p, x, y, w, h, 0, CopyFromParent, InputOutput,
|
|
CopyFromParent, CWOverrideRedirect|CWBackPixel, &attr);
|
|
XSelectInput(dpy, r, ExposureMask|ButtonPressMask|ButtonReleaseMask|
|
|
EnterWindowMask|LeaveWindowMask);
|
|
XSaveContext(dpy, r, client_context, (XPointer)c);
|
|
return r;
|
|
}
|
|
|
|
void spread_top_gadgets(Client *c)
|
|
{
|
|
int w=c->pwidth;
|
|
w-=23; XMoveWindow(dpy, c->depth, w, 0);
|
|
if(c->zoom) {
|
|
w-=23; XMoveWindow(dpy, c->zoom, w, 0);
|
|
}
|
|
if(c->iconify) {
|
|
w-=23; XMoveWindow(dpy, c->iconify, w, 0);
|
|
}
|
|
XResizeWindow(dpy, c->drag, c->dragw=mx(4, w-19), scr->bh);
|
|
}
|
|
|
|
void setclientborder(Client *c, int old, int new)
|
|
{
|
|
int wc=0;
|
|
int x=c->x, y=c->y, oldpw=c->pwidth, oldph=c->pheight;
|
|
old&=(Psizeright|Psizebottom|Psizetrans);
|
|
new&=(Psizeright|Psizebottom|Psizetrans);
|
|
if(new!=old) {
|
|
if((new & Psizeright)&&!(old & Psizeright))
|
|
{ c->pwidth+=14; wc++; }
|
|
else if((old & Psizeright)&&!(new & Psizeright))
|
|
{ c->pwidth-=14; wc++; }
|
|
if((new & Psizebottom)&&!(old & Psizebottom))
|
|
c->pheight+=8;
|
|
else if((old & Psizebottom)&&!(new & Psizebottom))
|
|
c->pheight-=8;
|
|
XResizeWindow(dpy, c->parent, c->pwidth, c->pheight);
|
|
if(c->resize)
|
|
XMoveWindow(dpy, c->resize, c->pwidth-18, c->pheight-10);
|
|
if(wc)
|
|
spread_top_gadgets(c);
|
|
}
|
|
c->proto = (c->proto&~(Psizeright|Psizebottom|Psizetrans)) | new;
|
|
c->framewidth=((new&Psizeright)?22:8);
|
|
c->frameheight=scr->bh+((new&Psizebottom)?10:2);
|
|
if(c->gravity==EastGravity || c->gravity==NorthEastGravity ||
|
|
c->gravity==SouthEastGravity)
|
|
x-=(c->pwidth-oldpw);
|
|
if(c->gravity==SouthGravity || c->gravity==SouthEastGravity ||
|
|
c->gravity==SouthWestGravity)
|
|
y-=(c->pheight-oldph);
|
|
if(x!=c->x || y!=c->y)
|
|
XMoveWindow(dpy, c->parent, c->x=x, c->y=y);
|
|
}
|
|
|
|
void resizeclientwindow(Client *c, int width, int height)
|
|
{
|
|
if(width!=c->pwidth || height!=c->pheight) {
|
|
int old_width=c->pwidth;
|
|
XResizeWindow(dpy, c->parent, c->pwidth=width, c->pheight=height);
|
|
if(width!=old_width)
|
|
spread_top_gadgets(c);
|
|
if(c->resize)
|
|
XMoveWindow(dpy, c->resize, c->pwidth-18, c->pheight-10);
|
|
if (!c->fullscreen)
|
|
XResizeWindow(dpy, c->window, c->pwidth-c->framewidth, c->pheight-c->frameheight);
|
|
if(c->shaped)
|
|
reshape_frame(c);
|
|
sendconfig(c);
|
|
}
|
|
}
|
|
|
|
static int resizable(XSizeHints *xsh)
|
|
{
|
|
int r=0;
|
|
if(xsh->width_inc) {
|
|
if(xsh->min_width+xsh->width_inc<=xsh->max_width)
|
|
r++;
|
|
}
|
|
if(xsh->height_inc) {
|
|
if(xsh->min_height+xsh->height_inc<=xsh->max_height)
|
|
r+=2;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
extern unsigned int meta_mask;
|
|
|
|
void reshape_frame(Client *c)
|
|
{
|
|
XRectangle r;
|
|
|
|
#ifdef HAVE_XSHAPE
|
|
if(!shape_extn)
|
|
return;
|
|
|
|
XShapeCombineShape(dpy, c->parent, ShapeBounding, 4, c->scr->bh, c->window,
|
|
ShapeBounding, ShapeSet);
|
|
|
|
r.x = 0;
|
|
r.y = 0;
|
|
r.width = c->pwidth;
|
|
r.height = c->scr->bh;
|
|
|
|
XShapeCombineRectangles(dpy, c->parent, ShapeBounding,
|
|
0, 0, &r, 1, ShapeUnion, Unsorted);
|
|
|
|
if(c->proto & Psizeright) {
|
|
r.x = c->pwidth-18;
|
|
r.y = 0;
|
|
r.width = 18;
|
|
r.height = c->pheight;
|
|
XShapeCombineRectangles(dpy, c->parent, ShapeBounding,
|
|
0, 0, &r, 1, ShapeUnion, Unsorted);
|
|
}
|
|
if(c->proto & Psizebottom) {
|
|
r.x = 0;
|
|
r.y = c->pheight-10;
|
|
r.width = c->pwidth;
|
|
r.height = 10;
|
|
XShapeCombineRectangles(dpy, c->parent, ShapeBounding,
|
|
0, 0, &r, 1, ShapeUnion, Unsorted);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void redrawclient(Client *);
|
|
|
|
void reparent(Client *c)
|
|
{
|
|
XWindowAttributes attr;
|
|
XSetWindowAttributes attr2;
|
|
XTextProperty screen_prop;
|
|
Scrn *s=scr;
|
|
int cb;
|
|
Window leader;
|
|
Client *lc;
|
|
struct mcmd_keygrab *kg;
|
|
extern struct mcmd_keygrab *keygrabs;
|
|
char **cargv = NULL;
|
|
int cargc;
|
|
int size_changed = 0;
|
|
|
|
getwmstate(c);
|
|
if(XGetTransientForHint(dpy, c->window, &leader) &&
|
|
!XFindContext(dpy, leader, client_context, (XPointer *)&lc) &&
|
|
lc != NULL) {
|
|
c->leader = lc;
|
|
if (lc->fsscr != NULL)
|
|
c->scr = lc->fsscr;
|
|
else
|
|
c->scr = lc->scr;
|
|
} else if(XGetTextProperty(dpy, c->window, &screen_prop, ATOMS[AMIWM_SCREEN])) {
|
|
do {
|
|
if(s->root == scr->root &&
|
|
(!s->deftitle[screen_prop.nitems])&&!strncmp(s->deftitle,
|
|
(char *)screen_prop.value, screen_prop.nitems))
|
|
break;
|
|
s=s->behind;
|
|
} while(s!=scr);
|
|
XFree(screen_prop.value);
|
|
c->scr=s;
|
|
} else if(XGetCommand(dpy, c->window, &cargv, &cargc)) {
|
|
XrmDatabase db = (XrmDatabase)NULL;
|
|
XrmValue value;
|
|
char *str_type;
|
|
static XrmOptionDescRec table [] = {
|
|
{"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL},
|
|
};
|
|
XrmParseCommand(&db, table, 1, "amiwm", &cargc, cargv);
|
|
if(XrmGetResource(db, "amiwm.screen", "Amiwm.Screen",
|
|
&str_type, &value) == True &&
|
|
value.size != 0) {
|
|
do {
|
|
if(s->root == scr->root &&
|
|
(!s->deftitle[value.size])&&!strncmp(s->deftitle, value.addr,
|
|
value.size))
|
|
break;
|
|
s=s->behind;
|
|
} while(s!=scr);
|
|
c->scr=s;
|
|
}
|
|
XrmDestroyDatabase (db);
|
|
}
|
|
scr=c->scr;
|
|
if(c->parent && c->parent != scr->root)
|
|
return;
|
|
getproto(c);
|
|
getwflags(c);
|
|
XAddToSaveSet(dpy, c->window);
|
|
XGetWindowAttributes(dpy, c->window, &attr);
|
|
c->colormap = attr.colormap;
|
|
c->old_bw = attr.border_width;
|
|
c->framewidth=8;
|
|
c->frameheight=scr->bh+2;
|
|
attr2.override_redirect=True;
|
|
|
|
|
|
grav_map_win_to_frame(c, attr.x, attr.y, &c->x, &c->y);
|
|
|
|
/* Note: this is half of framewidth */
|
|
if ((c->x < 0) || (c->x > scr->width)) {
|
|
c->x = 0;
|
|
}
|
|
/* Note: this is the menu size, but no window framing */
|
|
if ((c->y < scr->bh) || (c->y > scr->height)) {
|
|
c->y = scr->bh;
|
|
}
|
|
|
|
/*
|
|
* Check to make sure we're not created larger than the
|
|
* available desktop size
|
|
*/
|
|
if (attr.width > (scr->width - c->framewidth)) {
|
|
attr.width = (scr->width - c->framewidth);
|
|
size_changed = 1;
|
|
}
|
|
if (attr.height > (scr->height - c->frameheight)) {
|
|
attr.height = (scr->height - c->frameheight);
|
|
size_changed = 1;
|
|
}
|
|
|
|
c->pwidth = attr.width + c->framewidth;
|
|
c->pheight = attr.height + c->frameheight;
|
|
|
|
/*
|
|
* Note: if we adjusted c->pwidth / c->pheight then
|
|
* we need to call XResizeWindow on c->window.
|
|
*
|
|
* Do it before we reparent it just to make things
|
|
* easy.
|
|
*/
|
|
if (size_changed == 1) {
|
|
XResizeWindow(dpy, c->window, c->pwidth-c->framewidth,
|
|
c->pheight-c->frameheight);
|
|
}
|
|
|
|
/* Create the parent window that'll have our decoration */
|
|
c->parent=XCreateWindow(dpy, scr->back, c->x, c->y,
|
|
c->pwidth, c->pheight,
|
|
0, CopyFromParent, InputOutput, CopyFromParent,
|
|
CWOverrideRedirect, &attr2);
|
|
XSaveContext(dpy, c->parent, client_context, (XPointer)c);
|
|
XSaveContext(dpy, c->parent, screen_context, (XPointer)c->scr);
|
|
XSetWindowBackground(dpy, c->parent, scr->dri.dri_Pens[BACKGROUNDPEN]);
|
|
XSetWindowBorderWidth(dpy, c->window, 0);
|
|
|
|
/* Reparent time */
|
|
XReparentWindow(dpy, c->window, c->parent, 4, scr->bh);
|
|
XSelectInput(dpy, c->window, EnterWindowMask | LeaveWindowMask |
|
|
ColormapChangeMask | PropertyChangeMask |
|
|
(c->module? SubstructureNotifyMask:0));
|
|
#ifdef HAVE_XSHAPE
|
|
if(shape_extn)
|
|
XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
|
|
#endif
|
|
XSelectInput(dpy, c->parent, SubstructureRedirectMask |
|
|
SubstructureNotifyMask | StructureNotifyMask | ExposureMask |
|
|
EnterWindowMask | LeaveWindowMask | ButtonPressMask);
|
|
for(kg=keygrabs; kg; kg=kg->next)
|
|
XGrabKey(dpy, kg->keycode, kg->modifiers, c->window, False, GrabModeAsync,
|
|
GrabModeAsync);
|
|
cb=(resizable(c->sizehints)? prefs.sizeborder:0);
|
|
c->close=creategadget(c, c->parent, 0, 0, 19, scr->bh);
|
|
c->drag=creategadget(c, c->parent, 19, 0, 1, 1);
|
|
if(c->wflags&WF_NOICONIFY || c->leader != NULL) {
|
|
c->iconify=None;
|
|
}
|
|
else
|
|
c->iconify=creategadget(c, c->parent, 0, 0, 23, scr->bh);
|
|
if(cb)
|
|
c->zoom=creategadget(c, c->parent, 0, 0, 23, scr->bh);
|
|
c->depth=creategadget(c, c->parent, 0, 0, 23, scr->bh);
|
|
spread_top_gadgets(c);
|
|
setclientborder(c, 0, cb);
|
|
if(cb)
|
|
c->resize=creategadget(c, c->parent, c->pwidth-18, c->pheight-10, 18, 10);
|
|
c->shaped = 0;
|
|
#ifdef HAVE_XSHAPE
|
|
if(shape_extn) {
|
|
int xbs, ybs, cShaped, xcs, ycs;
|
|
unsigned int wbs, hbs, wcs, hcs;
|
|
XShapeQueryExtents (dpy, c->window, &c->shaped, &xbs, &ybs, &wbs, &hbs,
|
|
&cShaped, &xcs, &ycs, &wcs, &hcs);
|
|
if(c->shaped)
|
|
reshape_frame(c);
|
|
}
|
|
#endif
|
|
XMapSubwindows(dpy, c->parent);
|
|
sendconfig(c);
|
|
if (scr->deftitle != NULL)
|
|
setstringprop(c->window, ATOMS[AMIWM_SCREEN], scr->deftitle);
|
|
if(prefs.focus == FOC_CLICKTOTYPE)
|
|
XGrabButton(dpy, Button1, AnyModifier, c->parent, True,
|
|
ButtonPressMask, GrabModeSync, GrabModeAsync, None, wm_curs);
|
|
}
|
|
|
|
void redraw(Client *c, Window w)
|
|
{
|
|
if(w==c->parent) {
|
|
int x, y;
|
|
x=c->pwidth-((c->proto&Psizeright)?18:4);
|
|
y=c->pheight-((c->proto&Psizebottom)?10:2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, c->pwidth-1, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, c->pheight-1);
|
|
XDrawLine(dpy, w, scr->gc, 4, y, x, y);
|
|
XDrawLine(dpy, w, scr->gc, x, scr->bh, x, y);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 1, c->pheight-1, c->pwidth-1, c->pheight-1);
|
|
XDrawLine(dpy, w, scr->gc, c->pwidth-1, 1, c->pwidth-1, c->pheight-1);
|
|
XDrawLine(dpy, w, scr->gc, 3, scr->bh-1, 3, y);
|
|
XDrawLine(dpy, w, scr->gc, 3, scr->bh-1, x, scr->bh-1);
|
|
} else if(w==c->close) {
|
|
if(c->active) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XFillRectangle(dpy, w, scr->gc, 7, scr->h3, 4, scr->h7-scr->h3);
|
|
}
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 7, scr->h3, 4, scr->h7-scr->h3);
|
|
if(c->clicked==w) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 18, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, scr->bh-2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, scr->bh-1, 18, scr->bh-1);
|
|
XDrawLine(dpy, w, scr->gc, 18, 1, 18, scr->bh-1);
|
|
} else {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 18, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, scr->bh-1);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 1, scr->bh-1, 18, scr->bh-1);
|
|
XDrawLine(dpy, w, scr->gc, 18, 1, 18, scr->bh-1);
|
|
}
|
|
} else if(w==c->drag) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->active?FILLTEXTPEN:TEXTPEN]);
|
|
XSetBackground(dpy, scr->gc, scr->dri.dri_Pens[c->active?FILLPEN:BACKGROUNDPEN]);
|
|
#ifdef USE_FONTSETS
|
|
if(c->title)
|
|
XmbDrawImageString(dpy, w, scr->dri.dri_FontSet, scr->gc,
|
|
11, 1+scr->dri.dri_Ascent,
|
|
c->title, strlen(c->title));
|
|
#else
|
|
if(c->title.value)
|
|
XDrawImageString(dpy, w, scr->gc, 11, 1+scr->dri.dri_Ascent,
|
|
(char *)c->title.value, c->title.nitems);
|
|
#endif
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, c->dragw-1, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, scr->bh-2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, scr->bh-1, c->dragw-1, scr->bh-1);
|
|
XDrawLine(dpy, w, scr->gc, c->dragw-1, 1, c->dragw-1, scr->bh-1);
|
|
} else if(w==c->iconify) {
|
|
if(c->active) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XFillRectangle(dpy, w, scr->gc, 7, scr->h8-4, 4, 2);
|
|
}
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 7, scr->h8-4, 4, 2);
|
|
if(c->clicked==w) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->active? FILLPEN:BACKGROUNDPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 5, scr->h2, 12, scr->h8-scr->h2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 5, scr->h8-(scr->bh>11? 7:6), 9, (scr->bh>11? 7:6));
|
|
} else {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->active? FILLPEN:BACKGROUNDPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 5, scr->h8-(scr->bh>11? 7:6), 9, (scr->bh>11? 7:6));
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 5, scr->h2, 12, scr->h8-scr->h2);
|
|
}
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w?SHADOWPEN:SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 22, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, scr->bh-2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w?SHINEPEN:SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, scr->bh-1, 22, scr->bh-1);
|
|
XDrawLine(dpy, w, scr->gc, 22, 0, 22, scr->bh-1);
|
|
} else if(w==c->zoom) {
|
|
if(c->active) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w? SHINEPEN:FILLPEN]);
|
|
XFillRectangle(dpy, w, scr->gc, 5, scr->h2, 12, scr->h8-scr->h2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w? FILLPEN:SHINEPEN]);
|
|
XFillRectangle(dpy, w, scr->gc, 6, scr->h2, 5, scr->h5-scr->h2);
|
|
}
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 6, scr->h2, 5, scr->h5-scr->h2);
|
|
XDrawRectangle(dpy, w, scr->gc, 5, scr->h2, 7, scr->h5-scr->h2);
|
|
XDrawRectangle(dpy, w, scr->gc, 5, scr->h2, 12, scr->h8-scr->h2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w? SHADOWPEN:SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 22, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, scr->bh-2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w? SHINEPEN:SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, scr->bh-1, 22, scr->bh-1);
|
|
XDrawLine(dpy, w, scr->gc, 22, 0, 22, scr->bh-1);
|
|
} else if(w==c->depth) {
|
|
if(c->active) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[BACKGROUNDPEN]);
|
|
XFillRectangle(dpy, w, scr->gc, 4, scr->h2, 10, scr->h6-scr->h2);
|
|
}
|
|
if(c->clicked!=w) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 4, scr->h2, 10, scr->h6-scr->h2);
|
|
}
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->active?SHINEPEN:BACKGROUNDPEN]);
|
|
XFillRectangle(dpy, w, scr->gc, 8, scr->h4, 10, scr->h8-scr->h4);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawRectangle(dpy, w, scr->gc, 8, scr->h4, 10, scr->h8-scr->h4);
|
|
if(c->clicked==w)
|
|
XDrawRectangle(dpy, w, scr->gc, 4, scr->h2, 10, scr->h6-scr->h2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w? SHADOWPEN:SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 22, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, scr->bh-2);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[c->clicked==w? SHINEPEN:SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, scr->bh-1, 22, scr->bh-1);
|
|
XDrawLine(dpy, w, scr->gc, 22, 0, 22, scr->bh-1);
|
|
} else if(w==c->resize) {
|
|
static XPoint points[]={{4,6},{13,2},{14,2},{14,7},{4,7}};
|
|
if(c->active) {
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XFillPolygon(dpy, w, scr->gc, points, sizeof(points)/sizeof(points[0]), Convex, CoordModeOrigin);
|
|
}
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawLines(dpy, w, scr->gc, points, sizeof(points)/sizeof(points[0]), CoordModeOrigin);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHINEPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 16, 0);
|
|
XDrawLine(dpy, w, scr->gc, 0, 0, 0, 8);
|
|
XSetForeground(dpy, scr->gc, scr->dri.dri_Pens[SHADOWPEN]);
|
|
XDrawLine(dpy, w, scr->gc, 0, 9, 17, 9);
|
|
XDrawLine(dpy, w, scr->gc, 17, 0, 17, 9);
|
|
}
|
|
}
|
|
|
|
void redrawclient(Client *c)
|
|
{
|
|
unsigned long bgpix;
|
|
|
|
scr=c->scr;
|
|
if((!c->parent) || c->parent == scr->root)
|
|
return;
|
|
bgpix=scr->dri.dri_Pens[c->active?FILLPEN:BACKGROUNDPEN];
|
|
XSetWindowBackground(dpy, c->parent, bgpix);
|
|
XSetWindowBackground(dpy, c->close, bgpix);
|
|
XSetWindowBackground(dpy, c->drag, bgpix);
|
|
if(c->iconify)
|
|
XSetWindowBackground(dpy, c->iconify, bgpix);
|
|
if(c->zoom)
|
|
XSetWindowBackground(dpy, c->zoom, bgpix);
|
|
XSetWindowBackground(dpy, c->depth, bgpix);
|
|
if(c->resize)
|
|
XSetWindowBackground(dpy, c->resize, bgpix);
|
|
XClearWindow(dpy, c->parent);
|
|
XClearWindow(dpy, c->close);
|
|
XClearWindow(dpy, c->drag);
|
|
if(c->iconify)
|
|
XClearWindow(dpy, c->iconify);
|
|
if(c->zoom)
|
|
XClearWindow(dpy, c->zoom);
|
|
XClearWindow(dpy, c->depth);
|
|
if(c->resize)
|
|
XClearWindow(dpy, c->resize);
|
|
redraw(c, c->parent);
|
|
redraw(c, c->close);
|
|
redraw(c, c->drag);
|
|
if(c->iconify)
|
|
redraw(c, c->iconify);
|
|
if(c->zoom)
|
|
redraw(c, c->zoom);
|
|
redraw(c, c->depth);
|
|
if(c->resize)
|
|
redraw(c, c->resize);
|
|
}
|
|
|
|
extern Client *clickclient;
|
|
extern Window clickwindow;
|
|
extern Scrn *mbdclick, *mbdscr;
|
|
|
|
void clickenter()
|
|
{
|
|
if((scr=mbdscr)&& clickwindow == scr->menubardepth) {
|
|
mbdclick = scr;
|
|
redrawmenubar(scr, scr->menubardepth);
|
|
} else {
|
|
scr = clickclient->scr;
|
|
redraw(clickclient, clickclient->clicked=clickwindow);
|
|
}
|
|
}
|
|
|
|
void clickleave()
|
|
{
|
|
if((scr=mbdscr)&& clickwindow == scr->menubardepth) {
|
|
mbdclick = NULL;
|
|
redrawmenubar(scr, scr->menubardepth);
|
|
} else {
|
|
scr = clickclient->scr;
|
|
clickclient->clicked=None;
|
|
redraw(clickclient, clickwindow);
|
|
}
|
|
}
|
|
|
|
void gadgetclicked(Client *c, Window w, XEvent *e)
|
|
{
|
|
scr=c->scr;
|
|
redraw(c, clickwindow=(clickclient=c)->clicked=w);
|
|
}
|
|
|
|
void gadgetaborted(Client *c)
|
|
{
|
|
Window w;
|
|
scr=c->scr;
|
|
if((w=c->clicked)) {
|
|
c->clicked=None;
|
|
redraw(c, w);
|
|
}
|
|
clickwindow=None;
|
|
clickclient=NULL;
|
|
}
|
|
|
|
static Client *topmostmappedclient(Window *children, unsigned int nchildren)
|
|
{
|
|
int n;
|
|
Client *c;
|
|
for(n=nchildren-1; n>=0; --n)
|
|
if((!XFindContext(dpy, children[n], client_context, (XPointer*)&c)) &&
|
|
(children[n]==c->parent || children[n]==c->window) &&
|
|
c->state==NormalState)
|
|
return c;
|
|
return NULL;
|
|
}
|
|
|
|
static Client *bottommostmappedclient(Window *children, unsigned int nchildren)
|
|
{
|
|
int n;
|
|
Client *c;
|
|
for(n=0; n<nchildren; n++)
|
|
if((!XFindContext(dpy, children[n], client_context, (XPointer*)&c)) &&
|
|
children[n]==c->parent && c->state==NormalState)
|
|
return c;
|
|
return NULL;
|
|
}
|
|
|
|
void raiselowerclient(Client *c, int place)
|
|
{
|
|
Window r,p,*children;
|
|
unsigned int nchildren;
|
|
if(place!=PlaceOnTop &&
|
|
XQueryTree(dpy, scr->back, &r, &p, &children, &nchildren)) {
|
|
if(place==PlaceOnBottom || topmostmappedclient(children, nchildren)==c) {
|
|
Client *c2 = bottommostmappedclient(children, nchildren);
|
|
if(c2 != NULL && c2 != c) {
|
|
Window ws[2];
|
|
ws[0]=c2->parent;
|
|
ws[1]=c->parent;
|
|
XRestackWindows(dpy, ws, 2);
|
|
} else if(place!=PlaceOnBottom)
|
|
XRaiseWindow(dpy, c->parent);
|
|
} else
|
|
XRaiseWindow(dpy, c->parent);
|
|
if(children) XFree(children);
|
|
} else XRaiseWindow(dpy, c->parent);
|
|
}
|
|
|
|
extern void setfocus(Window);
|
|
extern Client *activeclient;
|
|
|
|
/*
|
|
* Lower the top most client.
|
|
*
|
|
* Update focus if required.
|
|
*/
|
|
void
|
|
lowertopmostclient(Scrn *scr)
|
|
{
|
|
Window r, p, *children;
|
|
unsigned int nchildren;
|
|
Client *c_top, *c_bot;
|
|
Window ws[2];
|
|
|
|
/* Query the list of windows under the active screen */
|
|
if (XQueryTree(dpy, scr->back, &r, &p, &children, &nchildren) == 0) {
|
|
fprintf(stderr, "%s: couldn't fetch the window list\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Grab the top most client
|
|
*/
|
|
c_top = topmostmappedclient(children, nchildren);
|
|
if (c_top == NULL) {
|
|
fprintf(stderr, "%s: couldn't get the top most mapped client\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* And the bottom most client.
|
|
*/
|
|
c_bot = bottommostmappedclient(children, nchildren);
|
|
if (c_bot == NULL) {
|
|
fprintf(stderr, "%s: couldn't get the bottom most mapped client\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* If we're doing click-to-focus, mark the old top-most window
|
|
* as inactive; mark the new top-most window as active and has focus.
|
|
*/
|
|
if (prefs.focus == FOC_CLICKTOTYPE) {
|
|
c_top->active = False;
|
|
c_bot->active = True;
|
|
activeclient = c_bot;
|
|
redrawclient(c_bot);
|
|
redrawclient(c_top);
|
|
setfocus(c_bot->window);
|
|
}
|
|
|
|
/*
|
|
* Push this to the bottom of the stack.
|
|
*/
|
|
ws[0]=c_bot->parent;
|
|
ws[1]=c_top->parent;
|
|
XRestackWindows(dpy, ws, 2);
|
|
|
|
/*
|
|
* Free the children list.
|
|
*/
|
|
if (children)
|
|
XFree(children);
|
|
}
|
|
|
|
/*
|
|
* Raise the bottom most client.
|
|
*
|
|
* Update focus if required.
|
|
*/
|
|
void
|
|
raisebottommostclient(Scrn *scr)
|
|
{
|
|
Window r, p, *children;
|
|
unsigned int nchildren;
|
|
Client *c_top, *c_bot;
|
|
|
|
/* Query the list of windows under the active screen */
|
|
if (XQueryTree(dpy, scr->back, &r, &p, &children, &nchildren) == 0) {
|
|
fprintf(stderr, "%s: couldn't fetch the window list\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Grab the top most client
|
|
*/
|
|
c_top = topmostmappedclient(children, nchildren);
|
|
if (c_top == NULL) {
|
|
fprintf(stderr, "%s: couldn't get the top most mapped client\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* And the bottom most client.
|
|
*/
|
|
c_bot = bottommostmappedclient(children, nchildren);
|
|
if (c_bot == NULL) {
|
|
fprintf(stderr, "%s: couldn't get the bottom most mapped client\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* If we're doing click-to-focus, mark the old top-most window
|
|
* as inactive; mark the new top-most window as active and has focus.
|
|
*/
|
|
if (prefs.focus == FOC_CLICKTOTYPE) {
|
|
c_top->active = False;
|
|
c_bot->active = True;
|
|
activeclient = c_bot;
|
|
redrawclient(c_bot);
|
|
redrawclient(c_top);
|
|
setfocus(c_bot->window);
|
|
}
|
|
|
|
/* Raise the selected window to the top */
|
|
XRaiseWindow(dpy, c_bot->parent);
|
|
|
|
/*
|
|
* Free the children list.
|
|
*/
|
|
if (children)
|
|
XFree(children);
|
|
}
|
|
|
|
|
|
void gadgetunclicked(Client *c, XEvent *e)
|
|
{
|
|
extern void adjusticon(Icon *);
|
|
Window w;
|
|
scr=c->scr;
|
|
if((w=c->clicked)) {
|
|
c->clicked=None;
|
|
redraw(c, w);
|
|
if(w==c->close) {
|
|
if((c->proto & Pdelete)&&!(e->xbutton.state&ShiftMask))
|
|
sendcmessage(c->window, ATOMS[WM_PROTOCOLS], ATOMS[WM_DELETE_WINDOW]);
|
|
else
|
|
XKillClient(dpy, c->window);
|
|
} else if(w==c->depth)
|
|
raiselowerclient(c, -1);
|
|
else if(w==c->zoom) {
|
|
XWindowAttributes xwa;
|
|
XGetWindowAttributes(dpy, c->parent, &xwa);
|
|
XMoveWindow(dpy, c->parent, c->x=c->zoomx, c->y=c->zoomy);
|
|
resizeclientwindow(c, c->zoomw+c->framewidth, c->zoomh+c->frameheight);
|
|
c->zoomx=xwa.x;
|
|
c->zoomy=xwa.y;
|
|
c->zoomw=xwa.width-c->framewidth;
|
|
c->zoomh=xwa.height-c->frameheight;
|
|
/* XWarpPointer(dpy, None, c->zoom, 0, 0, 0, 0, 23/2, scr->h5); */
|
|
sendconfig(c);
|
|
} else if(w==c->iconify) {
|
|
iconify(c);
|
|
}
|
|
}
|
|
clickwindow=None;
|
|
clickclient=NULL;
|
|
}
|