mirror of
https://github.com/amiwm/amiwm.git
synced 2026-03-24 01:24:15 +00:00
Previously, adding a new atom into the code required: 1. In <icc.h>, add the line `extern Atom my_new_atom;` declaring the new atom. 2. In <icc.c>, add the line `Atom my_new_atom;` defining the new atom. 3. In <icc.c>, add the line `my_new_atom = XInternAtom(dpy, "MY_NEW_ATOM", False);` interning this new atom, and assigning the interned value to the variable. Now, just add a line with the atom's name in the X-MACRO in <icc.h>, and a XInternAtoms(3) and a set of macros will do the rest. All new atoms will be referred to as an entry in the ATOMS[] array. For example: ATOMS[MY_NEW_ATOM] The exception are for those REALLY OLD atoms that have already a dedicated compile-time-known value defined at <X11/Xatom.h>. Those do not need to be interned; and are referred to with a constant beginning with the `XA_` prefix. For example: XA_WM_CLASS
421 lines
11 KiB
C
421 lines
11 KiB
C
#include <X11/Xlib.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "drawinfo.h"
|
|
#include "screen.h"
|
|
#include "icon.h"
|
|
#include "client.h"
|
|
#include "prefs.h"
|
|
#include "icc.h"
|
|
|
|
extern Display *dpy;
|
|
extern Cursor wm_curs;
|
|
#ifdef USE_FONTSETS
|
|
extern XFontSet labelfontset;
|
|
extern int labelfont_ascent;
|
|
#else
|
|
extern XFontStruct *labelfont;
|
|
#endif
|
|
extern char *progname;
|
|
extern XContext screen_context, client_context, vroot_context;
|
|
|
|
extern void createmenubar();
|
|
extern void reparent(Client *);
|
|
|
|
static Scrn *_front = NULL;
|
|
Scrn *scr = NULL;
|
|
|
|
/*
|
|
* Accessor methods to get and set the 'front' screen.
|
|
*/
|
|
Scrn *
|
|
get_front_scr(void)
|
|
{
|
|
return _front;
|
|
}
|
|
|
|
void
|
|
set_front_scr(Scrn *s)
|
|
{
|
|
_front = s;
|
|
}
|
|
|
|
static Scrn *getvroot(Window root)
|
|
{
|
|
Scrn *s;
|
|
if(!XFindContext(dpy, root, vroot_context, (XPointer *)&s))
|
|
return s;
|
|
return NULL;
|
|
}
|
|
|
|
static void setvroot(Window root, Scrn *s)
|
|
{
|
|
XSaveContext(dpy, root, vroot_context, (XPointer)s);
|
|
}
|
|
|
|
void setvirtualroot(Scrn *s)
|
|
{
|
|
if(s) {
|
|
Scrn *old_vroot = getvroot(s->root);
|
|
|
|
if(s==old_vroot) return;
|
|
if(old_vroot)
|
|
XDeleteProperty(dpy, old_vroot->back, ATOMS[__SWM_VROOT]);
|
|
setvroot(s->root, s);
|
|
XChangeProperty(dpy, s->back, ATOMS[__SWM_VROOT], XA_WINDOW, 32, PropModeReplace,
|
|
(unsigned char *)&(s->back), 1);
|
|
}
|
|
}
|
|
|
|
Scrn *getscreenbyrootext(Window w, int include_fs);
|
|
|
|
void screentoback(void)
|
|
{
|
|
Scrn *f;
|
|
if((!scr)||(scr->back==scr->root)) return;
|
|
if(scr == get_front_scr()) {
|
|
XLowerWindow(dpy, scr->back);
|
|
set_front_scr(scr->behind);
|
|
} else if(scr==getscreenbyrootext(scr->root, 1)) {
|
|
XLowerWindow(dpy, scr->back);
|
|
scr->upfront->behind=scr->behind;
|
|
scr->behind->upfront=scr->upfront;
|
|
scr->upfront = get_front_scr()->upfront;
|
|
scr->behind = get_front_scr();
|
|
get_front_scr()->upfront->behind=scr;
|
|
get_front_scr()->upfront=scr;
|
|
} else if(scr->behind == get_front_scr()) {
|
|
XRaiseWindow(dpy, scr->back);
|
|
set_front_scr(scr);
|
|
} else {
|
|
XRaiseWindow(dpy, scr->back);
|
|
scr->upfront->behind=scr->behind;
|
|
scr->behind->upfront=scr->upfront;
|
|
scr->upfront = get_front_scr()->upfront;
|
|
scr->behind = get_front_scr();
|
|
get_front_scr()->upfront->behind=scr;
|
|
get_front_scr()->upfront=scr;
|
|
set_front_scr(scr);
|
|
}
|
|
if((f = getscreenbyrootext(scr->root, 0))) {
|
|
init_dri(&f->dri, dpy, f->root, f->cmap, True);
|
|
setvirtualroot(f);
|
|
}
|
|
}
|
|
|
|
void assimilate(Window w, int x, int y)
|
|
{
|
|
#ifdef ASSIMILATE_WINDOWS
|
|
XSetWindowAttributes xsa;
|
|
|
|
XAddToSaveSet(dpy, w);
|
|
XReparentWindow(dpy, w, scr->back, x, (y<scr->y? 0:y-scr->y));
|
|
XSaveContext(dpy, w, screen_context, (XPointer)scr);
|
|
xsa.override_redirect = False;
|
|
XChangeWindowAttributes(dpy, w, CWOverrideRedirect, &xsa);
|
|
#endif
|
|
}
|
|
|
|
static void scanwins()
|
|
{
|
|
unsigned int i, nwins;
|
|
Client *c;
|
|
Window dw1, dw2, *wins;
|
|
XPointer dummy;
|
|
Scrn *s=scr;
|
|
|
|
XGrabServer(dpy);
|
|
XQueryTree(dpy, scr->root, &dw1, &dw2, &wins, &nwins);
|
|
for (int scan_dialogs = 0; nwins > 0 && scan_dialogs <= 1; scan_dialogs++) {
|
|
for (i = 0; i < nwins; i++) {
|
|
XWindowAttributes attr;
|
|
Window leader = None;
|
|
|
|
XGetTransientForHint(dpy, wins[i], &leader);
|
|
if (!scan_dialogs && leader != None)
|
|
continue; /* first pass; skip dialogs */
|
|
if (scan_dialogs && leader == None)
|
|
continue; /* second pass; skip leaders */
|
|
XGetWindowAttributes(dpy, wins[i], &attr);
|
|
if (!XFindContext(dpy, wins[i], client_context, &dummy))
|
|
continue;
|
|
if (attr.override_redirect) {
|
|
if(scr->back!=scr->root && XFindContext(dpy, wins[i], screen_context, &dummy))
|
|
assimilate(wins[i], attr.x, attr.y);
|
|
continue;
|
|
}
|
|
c = createclient(wins[i]);
|
|
if (c != NULL && c->window == wins[i]) {
|
|
if (attr.map_state == IsViewable) {
|
|
c->state=NormalState;
|
|
getstate(c);
|
|
reparent(c);
|
|
if(c->state==IconicState && c->leader == NULL) {
|
|
createicon(c);
|
|
adjusticon(c->icon);
|
|
XMapWindow(dpy, c->icon->window);
|
|
if(c->icon->labelwidth)
|
|
XMapWindow(dpy, c->icon->labelwin);
|
|
c->icon->mapped=1;
|
|
} else if(c->state==NormalState) {
|
|
XMapRaised(dpy, c->parent);
|
|
} else {
|
|
XRaiseWindow(dpy, c->parent);
|
|
}
|
|
c->reparenting=1;
|
|
scr=s;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
XUngrabServer(dpy);
|
|
XFree((void *) wins);
|
|
cleanupicons();
|
|
}
|
|
|
|
void closescreen(void)
|
|
{
|
|
Scrn *dummy;
|
|
|
|
if(scr->behind == scr)
|
|
scr->behind = NULL;
|
|
else {
|
|
scr->upfront->behind=scr->behind;
|
|
scr->behind->upfront=scr->upfront;
|
|
}
|
|
|
|
XDeleteContext(dpy,scr->menubardepth,screen_context);
|
|
XDestroyWindow(dpy,scr->menubardepth);
|
|
if (scr->menubarparent != None) {
|
|
XDeleteContext(dpy,scr->menubarparent,screen_context);
|
|
XDestroyWindow(dpy,scr->menubarparent);
|
|
}
|
|
XDeleteContext(dpy,scr->menubar,screen_context);
|
|
XDestroyWindow(dpy,scr->menubar);
|
|
if(scr->inputbox != None) {
|
|
XDeleteContext(dpy,scr->inputbox,screen_context);
|
|
XDestroyWindow(dpy,scr->inputbox);
|
|
}
|
|
|
|
XFreeGC(dpy,scr->rubbergc);
|
|
XFreeGC(dpy,scr->icongc);
|
|
XFreeGC(dpy,scr->gc);
|
|
XDeleteContext(dpy,scr->back,screen_context);
|
|
XDestroyWindow(dpy,scr->back);
|
|
free_icon_pms(&scr->default_tool_pms);
|
|
term_dri(&scr->dri, dpy, scr->cmap);
|
|
if(scr->iconcolorsallocated)
|
|
XFreeColors(dpy, scr->cmap, scr->iconcolor, scr->iconcolorsallocated, 0);
|
|
if(get_front_scr()==scr)
|
|
set_front_scr(scr->behind);
|
|
dummy=scr->behind;
|
|
free(scr);
|
|
scr=dummy;
|
|
}
|
|
|
|
Scrn *openscreen(char *deftitle, Window root)
|
|
{
|
|
Scrn *s;
|
|
XWindowAttributes attr;
|
|
XSetWindowAttributes swa;
|
|
XGCValues gcv;
|
|
extern char *label_font_name;
|
|
|
|
if(!root)
|
|
root = DefaultRootWindow(dpy);
|
|
|
|
XGetWindowAttributes(dpy, root, &attr);
|
|
|
|
s = (Scrn *)calloc(1, sizeof(Scrn));
|
|
s->root = root;
|
|
s->cmap = attr.colormap;
|
|
s->depth = attr.depth;
|
|
s->visual = attr.visual;
|
|
s->number = XScreenNumberOfScreen(attr.screen);
|
|
s->inputbox = None;
|
|
|
|
init_dri(&s->dri, dpy, s->root, s->cmap, True);
|
|
|
|
swa.background_pixel = s->dri.dri_Pens[BACKGROUNDPEN];
|
|
swa.override_redirect = True;
|
|
swa.colormap = attr.colormap;
|
|
swa.cursor = wm_curs;
|
|
swa.border_pixel = BlackPixel(dpy, DefaultScreen(dpy));
|
|
|
|
s->back = XCreateWindow(dpy, root,
|
|
-prefs.borderwidth, (s->y=0)-prefs.borderwidth,
|
|
s->width = attr.width, s->height = attr.height,
|
|
s->bw=prefs.borderwidth, CopyFromParent,
|
|
InputOutput, CopyFromParent,
|
|
CWBackPixel|CWOverrideRedirect|CWColormap|CWCursor|
|
|
CWBorderPixel,
|
|
&swa);
|
|
|
|
XSaveContext(dpy, s->back, screen_context, (XPointer)s);
|
|
|
|
gcv.background = s->dri.dri_Pens[BACKGROUNDPEN];
|
|
|
|
#ifdef USE_FONTSETS
|
|
s->gc = XCreateGC(dpy, s->back, GCBackground, &gcv);
|
|
|
|
if(!labelfontset) {
|
|
char **missing_charsets = NULL;
|
|
int n_missing_charsets = 0;
|
|
labelfontset = XCreateFontSet(dpy, label_font_name,
|
|
&missing_charsets,
|
|
&n_missing_charsets, NULL);
|
|
if(missing_charsets)
|
|
XFreeStringList(missing_charsets);
|
|
if(!labelfontset) {
|
|
fprintf(stderr, "%s: cannot open font %s\n", progname, label_font_name);
|
|
labelfontset = s->dri.dri_FontSet;
|
|
}
|
|
}
|
|
{
|
|
XFontStruct **fsl;
|
|
char **fnl;
|
|
if(XFontsOfFontSet(labelfontset, &fsl, &fnl) < 1) {
|
|
fprintf(stderr, "%s: fontset %s is empty\n", progname,
|
|
label_font_name);
|
|
exit(1);
|
|
}
|
|
labelfont_ascent = fsl[0]->ascent;
|
|
s->lh = fsl[0]->ascent+fsl[0]->descent;
|
|
}
|
|
gcv.foreground = s->dri.dri_Pens[TEXTPEN];
|
|
|
|
s->icongc = XCreateGC(dpy, s->back, GCForeground|GCBackground, &gcv);
|
|
#else
|
|
gcv.font = s->dri.dri_Font->fid;
|
|
|
|
s->gc = XCreateGC(dpy, s->back, GCBackground|GCFont, &gcv);
|
|
|
|
if(!labelfont)
|
|
if(!(labelfont = XLoadQueryFont(dpy, label_font_name))) {
|
|
fprintf(stderr, "%s: cannot open font %s\n", progname, label_font_name);
|
|
labelfont = s->dri.dri_Font;
|
|
}
|
|
|
|
s->lh = labelfont->ascent+labelfont->descent;
|
|
gcv.font = labelfont->fid;
|
|
gcv.foreground = s->dri.dri_Pens[TEXTPEN];
|
|
|
|
s->icongc = XCreateGC(dpy, s->back, GCForeground|GCBackground|GCFont, &gcv);
|
|
#endif
|
|
|
|
gcv.function = GXinvert;
|
|
gcv.subwindow_mode = IncludeInferiors;
|
|
|
|
s->rubbergc = XCreateGC(dpy, s->back, GCFunction|GCSubwindowMode, &gcv);
|
|
|
|
s->title = s->deftitle = deftitle;
|
|
|
|
s->default_tool_pms.pm = None;
|
|
s->default_tool_pms.pm2 = None;
|
|
s->default_tool_pms.cs.colors = NULL;
|
|
s->default_tool_pms.cs2.colors = NULL;
|
|
s->default_tool_pm_w=0;
|
|
s->default_tool_pm_h=0;
|
|
|
|
if(get_front_scr()) {
|
|
s->behind = get_front_scr();
|
|
s->upfront = get_front_scr()->upfront;
|
|
get_front_scr()->upfront->behind=s;
|
|
get_front_scr()->upfront=s;
|
|
} else {
|
|
s->behind = s->upfront = s;
|
|
set_front_scr(s);
|
|
}
|
|
|
|
scr=s;
|
|
|
|
return s;
|
|
}
|
|
|
|
void realizescreens(void)
|
|
{
|
|
scr = get_front_scr();
|
|
|
|
do {
|
|
if(!scr->realized) {
|
|
scr->fh = scr->dri.dri_Ascent+scr->dri.dri_Descent;
|
|
scr->bh=scr->fh+3;
|
|
scr->h2=(2*scr->bh)/10; scr->h3=(3*scr->bh)/10;
|
|
scr->h4=(4*scr->bh)/10; scr->h5=(5*scr->bh)/10;
|
|
scr->h6=(6*scr->bh)/10; scr->h7=(7*scr->bh)/10;
|
|
scr->h8=(8*scr->bh)/10;
|
|
createmenubar();
|
|
createdefaulticons();
|
|
|
|
if (scr->inputbox == None && prefs.focus == FOC_CLICKTOTYPE) {
|
|
scr->inputbox = XCreateWindow(dpy, scr->back, 0, 0,
|
|
scr->width, scr->height, 0, 0,
|
|
InputOnly, CopyFromParent, 0, NULL);
|
|
XSaveContext(dpy, scr->inputbox, screen_context, (XPointer)scr);
|
|
XSelectInput(dpy, scr->inputbox, KeyPressMask|KeyReleaseMask);
|
|
XLowerWindow(dpy, scr->inputbox);
|
|
XMapWindow(dpy, scr->inputbox);
|
|
}
|
|
|
|
XSelectInput(dpy, scr->root,
|
|
SubstructureNotifyMask|SubstructureRedirectMask|
|
|
KeyPressMask|KeyReleaseMask|
|
|
ButtonPressMask|ButtonReleaseMask|FocusChangeMask);
|
|
if(scr->back != scr->root)
|
|
XSelectInput(dpy, scr->back,
|
|
SubstructureNotifyMask|SubstructureRedirectMask|
|
|
KeyPressMask|KeyReleaseMask|
|
|
ButtonPressMask|ButtonReleaseMask);
|
|
|
|
if (scr->title)
|
|
XStoreName(dpy, scr->back, scr->title);
|
|
XLowerWindow(dpy, scr->back);
|
|
XMapWindow(dpy, scr->back);
|
|
if (!scr->deftitle)
|
|
scr->realized = 1;
|
|
}
|
|
scr=scr->behind;
|
|
} while(scr != get_front_scr());
|
|
do {
|
|
if(!scr->realized) {
|
|
scanwins();
|
|
if(!getvroot(scr->root)) {
|
|
init_dri(&scr->dri, dpy, scr->root, scr->cmap, True);
|
|
setvirtualroot(scr);
|
|
}
|
|
scr->realized=1;
|
|
}
|
|
scr=scr->behind;
|
|
} while(scr != get_front_scr());
|
|
}
|
|
|
|
Scrn *getscreen(Window w)
|
|
{
|
|
Scrn *s = get_front_scr();
|
|
if(w && s)
|
|
do {
|
|
if(s->back == w || s->root == w)
|
|
return s;
|
|
s=s->behind;
|
|
} while(s != get_front_scr());
|
|
return get_front_scr();
|
|
}
|
|
|
|
Scrn *getscreenbyrootext(Window w, int include_fs)
|
|
{
|
|
Scrn *s = get_front_scr();
|
|
if(s)
|
|
do {
|
|
if(s->root == w && (include_fs || s->deftitle))
|
|
return s;
|
|
s=s->behind;
|
|
} while(s != get_front_scr());
|
|
return NULL;
|
|
}
|
|
|
|
Scrn *getscreenbyroot(Window w)
|
|
{
|
|
return getscreenbyrootext(w, 0);
|
|
}
|