#include #include #include #include #include #include "drawinfo.h" #include "screen.h" #include "icon.h" #include "client.h" #include "icc.h" #include "prefs.h" #ifdef AMIGAOS #include extern struct Library *XLibBase; #endif extern Display *dpy; extern XContext client_context, screen_context; extern Client *activeclient; extern Scrn *menuactive; extern void setfocus(Window); Client *clients=NULL; void grav_map_frame_to_win(Client *c, int x0, int y0, int *x, int *y) { switch(c->gravity) { case EastGravity: case NorthEastGravity: case SouthEastGravity: *x=x0+c->framewidth-c->old_bw-c->old_bw; break; case CenterGravity: case NorthGravity: case SouthGravity: *x=x0+4-c->old_bw; break; case WestGravity: case NorthWestGravity: case SouthWestGravity: default: *x=x0; break; } switch(c->gravity) { case SouthGravity: case SouthEastGravity: case SouthWestGravity: *y=y0+c->frameheight-c->old_bw-c->old_bw; break; case CenterGravity: case EastGravity: case WestGravity: *y=y0+c->scr->bh-c->old_bw; break; case NorthGravity: case NorthEastGravity: case NorthWestGravity: default: *y=y0; break; } } void grav_map_win_to_frame(Client *c, int x0, int y0, int *x, int *y) { switch(c->gravity) { case EastGravity: case NorthEastGravity: case SouthEastGravity: *x=x0-c->framewidth+c->old_bw+c->old_bw; break; case CenterGravity: case NorthGravity: case SouthGravity: *x=x0-4+c->old_bw; break; case WestGravity: case NorthWestGravity: case SouthWestGravity: default: *x=x0; break; } switch(c->gravity) { case SouthGravity: case SouthEastGravity: case SouthWestGravity: *y=y0-c->frameheight+c->old_bw+c->old_bw; break; case CenterGravity: case EastGravity: case WestGravity: *y=y0-c->scr->bh+c->old_bw; break; case NorthGravity: case NorthEastGravity: case NorthWestGravity: default: *y=y0; break; } } void sendconfig(Client *c) { XConfigureEvent ce; ce.type = ConfigureNotify; ce.event = c->window; ce.window = c->window; /* grav_map_frame_to_win(c, c->x, c->y, &ce.x, &ce.y); */ ce.x = c->x+4; #ifndef ASSIMILATE_WINDOWS ce.y = c->y+c->scr->bh+c->scr->y; #else ce.y = c->y+c->scr->bh; #endif ce.width = c->pwidth-c->framewidth; ce.height = c->pheight-c->frameheight; ce.border_width = c->old_bw; ce.above = None; ce.override_redirect = 0; XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent*)&ce); XSync(dpy, False); } void scrsendconfig(Scrn *s) { Client *c; for (c=clients; c; c = c->next) if(c->scr == s) sendconfig(c); } void checksizehints(Client *c) { long supplied; XGetWMNormalHints(dpy, c->window, c->sizehints, &supplied); if(!(c->sizehints->flags&PMinSize)) c->sizehints->min_width=c->sizehints->min_height=0; if(!(c->sizehints->flags&PMaxSize)) c->sizehints->max_width=c->sizehints->max_height=1<<30; if(!(c->sizehints->flags&PResizeInc)) c->sizehints->width_inc=c->sizehints->height_inc=1; if(c->sizehints->flags&PBaseSize) { c->sizehints->min_width=c->sizehints->base_width; c->sizehints->min_height=c->sizehints->base_height; } if(c->sizehints->min_width<1) c->sizehints->min_width=1; if(c->sizehints->min_height<1) c->sizehints->min_height=1; c->sizehints->base_width=c->sizehints->min_width; c->sizehints->base_height=c->sizehints->min_height; if(c->sizehints->flags&PWinGravity) c->gravity=c->sizehints->win_gravity; } void open_fscrn(Client *c) { c->fsscr = scr = openscreen(NULL, scr->root); c->reparenting = 1; XReparentWindow(dpy, c->parent, c->fsscr->back, 0, 0); XRaiseWindow(dpy, c->window); XMoveResizeWindow(dpy, c->parent, 0, 0, c->fsscr->width, c->fsscr->height); XMoveResizeWindow(dpy, c->window, 0, 0, c->fsscr->width, c->fsscr->height); for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) if (dialog->leader == c) reparent_client(c->fsscr, dialog); XResizeWindow(dpy, c->window, scr->width, scr->height); realizescreens(); scr = c->fsscr; #ifdef USE_FONTSETS XStoreName(dpy, scr->back, c->title); #else XSetWMName(dpy, scr->back, &c->title); #endif screentoback(); } void close_fscrn(Client *c, int state) { if (c->fsscr == NULL) return; XReparentWindow(dpy, c->parent, c->scr->back, c->x, c->y); XMoveResizeWindow(dpy, c->parent, c->x, c->y, c->pwidth, c->pheight); XMoveResizeWindow(dpy, c->window, 4, c->scr->bh, c->pwidth-c->framewidth, c->pheight-c->frameheight); XResizeWindow(dpy, c->window, c->pwidth-c->framewidth, c->pheight-c->frameheight); XLowerWindow(dpy, c->window); scr = c->fsscr; closescreen(); c->fsscr = NULL; scr = c->scr; if (state != IconicState) XMapWindow(dpy, c->parent); for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) if (dialog->leader == c) reparent_client(c->scr, dialog); } void setclientstate(Client *c, int state) { long data[2]; data[0] = (long) state; data[1] = (long) None; if (c->fullscreen) { if (state != NormalState && c->state == NormalState) { close_fscrn(c, state); } else if (state == NormalState && c->state != NormalState) { open_fscrn(c); } } c->state = state; XChangeProperty(dpy, c->window, ATOMS[WM_STATE], ATOMS[WM_STATE], 32, PropModeReplace, (unsigned char *)data, 2); } void getstate(Client *c) { long *data=NULL; if(_getprop(c->window, ATOMS[WM_STATE], ATOMS[WM_STATE], 2l, (char **)&data)>0) { c->state=*data; XFree((char *)data); } } Client *createclient(Window w) { extern void checkstyle(Client *c); XWindowAttributes attr; Client *c; int b = 0; if(w==0) return 0; if(!XFindContext(dpy, w, client_context, (XPointer*)&c)) return c; XGetWindowAttributes(dpy, w, &attr); c = (Client *)calloc(1, sizeof(Client)); c->sizehints = XAllocSizeHints(); c->scr = scr; c->fsscr = NULL; c->window = w; c->parent = scr->root; c->old_bw = attr.border_width; c->next = clients; c->state = WithdrawnState; c->gravity = NorthWestGravity; c->reparenting = 0; c->fullscreen = 0; XSelectInput(dpy, c->window, PropertyChangeMask); #ifdef USE_FONTSETS { XTextProperty prop; c->title = NULL; if(XGetWMName(dpy, c->window, &prop) && prop.value) { char **list; int n; if(XmbTextPropertyToTextList(dpy, &prop, &list, &n) >= Success) { if(n > 0) c->title = strdup(list[0]); XFreeStringList(list); } XFree(prop.value); } } #else XGetWMName(dpy, c->window, &c->title); #endif c->style = NULL; checkstyle(c); checksizehints(c); c->zoomx=0; c->zoomy=scr->bh; if ((c->sizehints->width_inc && c->sizehints->min_width+c->sizehints->width_inc<=c->sizehints->max_width)|| (c->sizehints->height_inc && c->sizehints->min_height+c->sizehints->height_inc<=c->sizehints->max_height)) b = prefs.sizeborder; if(c->sizehints->width_inc) { c->zoomw=scr->width-c->sizehints->base_width; if (b & Psizeright) c->zoomw-=22; else c->zoomw-=8; c->zoomw-=c->zoomw%c->sizehints->width_inc; c->zoomw+=c->sizehints->base_width; if(c->zoomw>c->sizehints->max_width) c->zoomw=c->sizehints->max_width; if(c->zoomwsizehints->min_width) c->zoomw=c->sizehints->min_width; } else c->zoomw=attr.width; if(c->sizehints->height_inc) { c->zoomh=scr->height-c->sizehints->base_height-scr->bh-c->zoomy; if (b & Psizebottom) c->zoomh -= 10; else c->zoomh -= 2; c->zoomh-=c->zoomh%c->sizehints->height_inc; c->zoomh+=c->sizehints->base_height; if(c->zoomh>c->sizehints->max_height) c->zoomh=c->sizehints->max_height; if(c->zoomhsizehints->min_height) c->zoomh=c->sizehints->min_height; } else c->zoomh=attr.height; XSaveContext(dpy, w, client_context, (XPointer)c); return clients = c; } void rmclient(Client *c) { Client *cc; if (c == clients) clients = c->next; else if((cc = clients)) for (; cc->next; cc = cc->next) if (cc->next == c) { cc->next = cc->next->next; break; } if ((scr = c->fsscr)) closescreen(); scr = c->scr; if(c->active) { if(!menuactive) setfocus(None); c->active=False; activeclient = NULL; XInstallColormap(dpy, scr->cmap); } else if(prefs.focus==FOC_CLICKTOTYPE) XUngrabButton(dpy, Button1, AnyModifier, c->parent); #ifdef USE_FONTSETS if(c->title) free(c->title); #else if(c->title.value) XFree(c->title.value); #endif if(c->parent != c->scr->root) { XDestroyWindow(dpy, c->parent); XDeleteContext(dpy, c->parent, client_context); } if(c->close) XDeleteContext(dpy, c->close, client_context); if(c->drag) XDeleteContext(dpy, c->drag, client_context); if(c->iconify) XDeleteContext(dpy, c->iconify, client_context); if(c->zoom) XDeleteContext(dpy, c->zoom, client_context); if(c->depth) XDeleteContext(dpy, c->depth, client_context); if(c->resize) XDeleteContext(dpy, c->resize, client_context); if(c->icon) rmicon(c->icon); if(c->window) XDeleteContext(dpy, c->window, client_context); if (c->sizehints) XFree(c->sizehints); for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) if (dialog->leader == c) dialog->leader = NULL; free(c); } int screen_has_clients() { int n = 0; Client *c = clients; while(c) { if(c->scr == scr) n++; c = c->next; } return n; } void flushclients() { unsigned int i, nwins; Window dw1, dw2, *wins; Client *c; #ifdef ASSIMILATE_WINDOWS Scrn *scr2; #endif if((scr = get_front_scr())) do { scr = scr->upfront; XQueryTree(dpy, scr->back, &dw1, &dw2, &wins, &nwins); for(i=0; iparent) { int x,y; grav_map_frame_to_win(c, c->x, c->y, &x, &y); XReparentWindow(dpy, c->window, scr->root, x, y); XSetWindowBorderWidth(dpy, c->window, c->old_bw); XRemoveFromSaveSet(dpy, c->window); wins[i]=c->window; rmclient(c); } #ifdef ASSIMILATE_WINDOWS else if((!XFindContext(dpy, wins[i], screen_context, (XPointer *)&scr2)) && scr2==scr) { XWindowAttributes attr; XSetWindowAttributes xsa; XGetWindowAttributes(dpy, wins[i], &attr); XReparentWindow(dpy, wins[i], scr->root, attr.x, attr.y); xsa.override_redirect = True; XChangeWindowAttributes(dpy, wins[i], CWOverrideRedirect, &xsa); XDeleteContext(dpy, wins[i], screen_context); XRemoveFromSaveSet(dpy, wins[i]); } #endif /* if(nwins) { for(i=0; i<(nwins>>1); i++) { Window w=wins[i]; wins[i]=wins[nwins-1-i]; wins[nwins-1-i]=w; } XRestackWindows(dpy, wins, nwins); } */ XFree((void *) wins); } while( scr!= get_front_scr()); while((c=clients)) { if(c->parent != c->scr->root) { int x,y; grav_map_frame_to_win(c, c->x, c->y, &x, &y); XReparentWindow(dpy, c->window, c->scr->root, x, y); XSetWindowBorderWidth(dpy, c->window, c->old_bw); XRemoveFromSaveSet(dpy, c->window); } rmclient(c); } } /* * Reparent the given client to the given screen. * * This moves the given client to the given screen. */ void reparent_client(Scrn *s, Client *client) { client->scr = s; if(client->parent != client->scr->root) XReparentWindow(dpy, client->parent, s->back, client->x, client->y); if (s->deftitle != NULL) setstringprop(client->window, ATOMS[AMIWM_SCREEN], s->deftitle); sendconfig(client); } void fullscreen(Client *c, int fs) { if (fs == c->fullscreen) return; if (c->state != NormalState) { c->fullscreen = fs; setwmstate(c); return; } if (fs) { open_fscrn(c); c->fullscreen = 1; } else { close_fscrn(c, c->state); c->fullscreen = 0; setclientstate(c, NormalState); } setwmstate(c); }