mirror of
https://github.com/amiwm/amiwm.git
synced 2026-03-24 01:24:15 +00:00
This commit implements the _NET_SUPPORTING_WM_CHECK property, defined by the EWMH[1] (Extended Window Management Hints, aka wm-spec), which indicates that a EWMH-compliant window manager is running. A GTK application, when set to go fullscreen, first checks root window's _NET_SUPPORTING_WM_CHECK property to determine whether a EWMH-compliant window manager is running; and then checks the _NET_SUPPORTED property to determine the supported protocols. _NET_SUPPORTED was previously implemented, but _NET_SUPPORTING_WM_CHECK was not. This commit also fixes a misconception of the code related to screens. The code deals with two different, unrelated concepts of screens: the X11 screen, and the AmiWM screen. The X11 screen, created by the X server independently of whether a window manager is running, is a kind of “subdisplay”. A X11 display structure, which describes a connection to the X server, has one or more screens. Each X11 screen has its own root window and its own set of clients that are specific to it, and cannot move to another X11 screen. The user can even run two different window managers at the same time in the same display, given that each is run in a different X11 screen. Usually, there is only one X11 screen. The _NET_SUPPORTING_WM_CHECK and _NET_SUPPORTED properties must be set on the root window of each screen that AmiWM is managing. Previously, however, they were set everytime an AmiWM screen (a totally different concept) was realized. So, if i had 4 AmiWM screens configured in my ~/.amiwmrc file, setsupports() were called four times, even if i only have a single X11 screen. [1]: https://specifications.freedesktop.org/wm/latest/index.html
413 lines
10 KiB
C
413 lines
10 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, swm_vroot);
|
|
setvroot(s->root, s);
|
|
XChangeProperty(dpy, s->back, 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;
|
|
XWindowAttributes *pattr=NULL;
|
|
XPointer dummy;
|
|
Scrn *s=scr;
|
|
|
|
XQueryTree(dpy, scr->root, &dw1, &dw2, &wins, &nwins);
|
|
if(nwins && (pattr=calloc(nwins, sizeof(XWindowAttributes)))) {
|
|
for (i = 0; i < nwins; i++)
|
|
XGetWindowAttributes(dpy, wins[i], pattr+i);
|
|
for (i = 0; i < nwins; i++) {
|
|
if (!XFindContext(dpy, wins[i], client_context, &dummy))
|
|
continue;
|
|
if (pattr[i].override_redirect) {
|
|
if(scr->back!=scr->root && XFindContext(dpy, wins[i], screen_context, &dummy))
|
|
assimilate(wins[i], pattr[i].x, pattr[i].y);
|
|
continue;
|
|
}
|
|
c = createclient(wins[i]);
|
|
if (c != 0 && c->window == wins[i]) {
|
|
if (pattr[i].map_state == IsViewable) {
|
|
c->state=NormalState;
|
|
getstate(c);
|
|
reparent(c);
|
|
if(c->state==IconicState) {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
free(pattr);
|
|
}
|
|
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);
|
|
}
|