/*
* ion/ioncore/rootwin.c
*
- * Copyright (c) Tuomo Valkonen 1999-2006.
+ * Copyright (c) Tuomo Valkonen 1999-2007.
*
- * Ion is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
*/
#include <unistd.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
-/*#include <X11/Xmu/Error.h>*/
-#ifdef CF_XINERAMA
-#include <X11/extensions/Xinerama.h>
-#elif defined(CF_SUN_XINERAMA)
-#include <X11/extensions/xinerama.h>
-#endif
#include <libtu/objp.h>
#include "common.h"
}
-static WRootWin *preinit_rootwin(int xscr)
+static Atom net_virtual_roots=None;
+
+
+static bool rootwin_init(WRootWin *rootwin, int xscr)
{
Display *dpy=ioncore_g.dpy;
- WRootWin *rootwin;
WFitParams fp;
Window root;
- int i;
/* Try to select input on the root window */
root=RootWindow(dpy, xscr);
redirect_error=FALSE;
XSetErrorHandler(my_redirect_error_handler);
- XSelectInput(dpy, root, IONCORE_EVENTMASK_ROOT);
+ XSelectInput(dpy, root, IONCORE_EVENTMASK_ROOT|IONCORE_EVENTMASK_SCREEN);
XSync(dpy, 0);
XSetErrorHandler(my_error_handler);
if(redirect_error){
warn(TR("Unable to redirect root window events for screen %d."),
xscr);
- return NULL;
+ return FALSE;
}
- rootwin=ALLOC(WRootWin);
-
- if(rootwin==NULL)
- return NULL;
-
- /* Init the struct */
- OBJ_INIT(rootwin, WRootWin);
-
rootwin->xscr=xscr;
rootwin->default_cmap=DefaultColormap(dpy, xscr);
rootwin->tmpwins=NULL;
fp.g.w=DisplayWidth(dpy, xscr);
fp.g.h=DisplayHeight(dpy, xscr);
- if(!window_do_init((WWindow*)rootwin, NULL, root, &fp)){
+ if(!screen_init((WScreen*)rootwin, NULL, &fp, xscr, root)){
free(rootwin);
- return NULL;
+ return FALSE;
}
- /* Note: this mask isn't right if some WScreen auses the same window. */
- ((WWindow*)rootwin)->event_mask=IONCORE_EVENTMASK_ROOT;
-
+ ((WWindow*)rootwin)->event_mask=IONCORE_EVENTMASK_ROOT|IONCORE_EVENTMASK_SCREEN;
((WRegion*)rootwin)->flags|=REGION_BINDINGS_ARE_GRABBED|REGION_PLEASE_WARP;
((WRegion*)rootwin)->rootwin=rootwin;
preinit_gr(rootwin);
netwm_init_rootwin(rootwin);
- region_add_bindmap((WRegion*)rootwin, ioncore_rootwin_bindmap);
-
- return rootwin;
-}
-
-
-static Atom net_virtual_roots=None;
-
+ net_virtual_roots=XInternAtom(ioncore_g.dpy, "_NET_VIRTUAL_ROOTS", False);
+ XDeleteProperty(ioncore_g.dpy, root, net_virtual_roots);
-static WScreen *add_screen(WRootWin *rw, int id, const WRectangle *geom,
- bool useroot)
-{
- WScreen *scr;
- CARD32 p[1];
- WFitParams fp;
-
- fp.g=*geom;
- fp.mode=REGION_FIT_EXACT;
-
-#ifdef CF_ALWAYS_VIRTUAL_ROOT
- useroot=FALSE;
-#endif
+ LINK_ITEM(*(WRegion**)&ioncore_g.rootwins, (WRegion*)rootwin, p_next, p_prev);
- scr=create_screen(rw, id, &fp, useroot);
+ xwindow_set_cursor(root, IONCORE_CURSOR_DEFAULT);
- if(scr==NULL)
- return NULL;
-
- region_set_manager((WRegion*)scr, (WRegion*)rw);
-
- region_map((WRegion*)scr);
-
- if(!useroot){
- p[0]=region_xwindow((WRegion*)scr);
- XChangeProperty(ioncore_g.dpy, WROOTWIN_ROOT(rw), net_virtual_roots,
- XA_WINDOW, 32, PropModeAppend, (uchar*)&(p[0]), 1);
- }
-
- return scr;
-}
-
-
-#ifdef CF_XINERAMA
-static bool xinerama_sanity_check(XineramaScreenInfo *xi, int nxi)
-{
- int i, j;
-
- for(i=0; i<nxi; i++){
- for(j=0; j<nxi; j++){
- if(i!=j &&
- (xi[j].x_org>=xi[i].x_org && xi[j].x_org<xi[i].x_org+xi[i].width) &&
- (xi[j].y_org>=xi[i].y_org && xi[j].y_org<xi[i].y_org+xi[i].height)){
- warn(TR("Xinerama sanity check failed; overlapping "
- "screens detected."));
- return FALSE;
- }
- }
-
- if(xi[i].width<=0 || xi[i].height<=0){
- warn(TR("Xinerama sanity check failed; zero size detected."));
- return FALSE;
- }
- }
- return TRUE;
-}
-#elif defined(CF_SUN_XINERAMA)
-static bool xinerama_sanity_check(XRectangle *monitors, int nxi)
-{
- int i, j;
-
- for(i=0; i<nxi; i++){
- for(j=0; j<nxi; j++){
- if(i!=j &&
- (monitors[j].x>=monitors[i].x &&
- monitors[j].x<monitors[i].x+monitors[i].width) &&
- (monitors[j].y>=monitors[i].y &&
- monitors[j].y<monitors[i].y+monitors[i].height)){
- warn(TR("Xinerama sanity check failed; overlapping "
- "screens detected."));
- return FALSE;
- }
- }
-
- if(monitors[i].width<=0 || monitors[i].height<=0){
- warn(TR("Xinerama sanity check failed; zero size detected."));
- return FALSE;
- }
- }
return TRUE;
}
-#endif
-WRootWin *ioncore_manage_rootwin(int xscr, bool noxinerama)
+WRootWin *create_rootwin(int xscr)
{
- WRootWin *rootwin;
- int nxi=0, fail=0;
-#ifdef CF_XINERAMA
- XineramaScreenInfo *xi=NULL;
- int i;
- int event_base, error_base;
-#elif defined(CF_SUN_XINERAMA)
- XRectangle monitors[MAXFRAMEBUFFERS];
- int i;
-#endif
-
- if(!noxinerama){
-#ifdef CF_XINERAMA
- if(XineramaQueryExtension(ioncore_g.dpy, &event_base, &error_base)){
- xi=XineramaQueryScreens(ioncore_g.dpy, &nxi);
-
- if(xi!=NULL && ioncore_g.rootwins!=NULL){
- warn(TR("Don't know how to get Xinerama information for "
- "multiple X root windows."));
- XFree(xi);
- xi=NULL;
- nxi=0;
- }
- }
-#elif defined(CF_SUN_XINERAMA)
- if(XineramaGetState(ioncore_g.dpy, xscr)){
- unsigned char hints[16];
- int num;
-
- if(XineramaGetInfo(ioncore_g.dpy, xscr, monitors, hints,
- &nxi)==0){
- warn(TR("Error retrieving Xinerama information."));
- nxi=0;
- }else{
- if(ioncore_g.rootwins!=NULL){
- warn(TR("Don't know how to get Xinerama information for "
- "multiple X root windows."));
- nxi=0;
- }
- }
- }
-#endif
- }
-
- rootwin=preinit_rootwin(xscr);
-
- if(rootwin==NULL){
-#ifdef CF_XINERAMA
- if(xi!=NULL)
- XFree(xi);
-#endif
- return NULL;
- }
-
- net_virtual_roots=XInternAtom(ioncore_g.dpy, "_NET_VIRTUAL_ROOTS", False);
- XDeleteProperty(ioncore_g.dpy, WROOTWIN_ROOT(rootwin), net_virtual_roots);
-
-#ifdef CF_XINERAMA
- if(xi!=NULL && nxi!=0 && xinerama_sanity_check(xi, nxi)){
- bool useroot=FALSE;
- WRectangle geom;
-
- for(i=0; i<nxi; i++){
- geom.x=xi[i].x_org;
- geom.y=xi[i].y_org;
- geom.w=xi[i].width;
- geom.h=xi[i].height;
- /*if(nxi==1)
- useroot=(geom.x==0 && geom.y==0);*/
- if(!add_screen(rootwin, i, &geom, useroot)){
- warn(TR("Unable to setup Xinerama screen %d."), i);
- fail++;
- }
- }
- XFree(xi);
- }else
-#elif defined(CF_SUN_XINERAMA)
- if(nxi!=0 && xinerama_sanity_check(monitors, nxi)){
- bool useroot=FALSE;
- WRectangle geom;
-
- for(i=0; i<nxi; i++){
- geom.x=monitors[i].x;
- geom.y=monitors[i].y;
- geom.w=monitors[i].width;
- geom.h=monitors[i].height;
- /*if(nxi==1)
- useroot=(geom.x==0 && geom.y==0);*/
- if(!add_screen(rootwin, i, &geom, useroot)){
- warn(TR("Unable to setup Xinerama screen %d."), i);
- fail++;
- }
- }
- }else
-#endif
- {
- nxi=1;
- if(!add_screen(rootwin, xscr, ®ION_GEOM(rootwin), TRUE))
- fail++;
- }
-
- if(fail==nxi){
- warn(TR("Unable to setup X screen %d."), xscr);
- destroy_obj((Obj*)rootwin);
- return NULL;
- }
-
- /* */ {
- /* TODO: typed LINK_ITEM */
- WRegion *tmp=(WRegion*)ioncore_g.rootwins;
- LINK_ITEM(tmp, (WRegion*)rootwin, p_next, p_prev);
- ioncore_g.rootwins=(WRootWin*)tmp;
- }
-
- xwindow_set_cursor(WROOTWIN_ROOT(rootwin), IONCORE_CURSOR_DEFAULT);
-
- return rootwin;
+ CREATEOBJ_IMPL(WRootWin, rootwin, (p, xscr));
}
destroy_obj((Obj*)scr);
}
- /* */ {
- WRegion *tmp=(WRegion*)ioncore_g.rootwins;
- UNLINK_ITEM(tmp, (WRegion*)rw, p_next, p_prev);
- ioncore_g.rootwins=(WRootWin*)tmp;
- }
+ UNLINK_ITEM(*(WRegion**)&ioncore_g.rootwins, (WRegion*)rw, p_next, p_prev);
XSelectInput(ioncore_g.dpy, WROOTWIN_ROOT(rw), 0);
XFreeGC(ioncore_g.dpy, rw->xor_gc);
- window_deinit((WWindow*)rw);
+ rw->scr.mplex.win.win=None;
+
+ screen_deinit(&rw->scr);
}
/*{{{ region dynfun implementations */
-static void rootwin_do_set_focus(WRootWin *rootwin, bool warp)
-{
- WRegion *sub;
-
- sub=REGION_ACTIVE_SUB(rootwin);
-
- if(sub==NULL || !REGION_IS_MAPPED(sub)){
- WScreen *scr;
- FOR_ALL_SCREENS(scr){
- if(REGION_IS_MAPPED(scr)){
- sub=(WRegion*)scr;
- break;
- }
- }
- }
-
- if(sub!=NULL)
- region_do_set_focus(sub, warp);
- else
- window_do_set_focus((WWindow*)rootwin, warp);
-}
-
-
static bool rootwin_fitrep(WRootWin *rootwin, WWindow *par,
const WFitParams *fp)
{
}
-static void rootwin_managed_remove(WRootWin *rootwin, WRegion *reg)
-{
- region_unset_manager(reg, (WRegion*)rootwin);
-}
-
-
-static Window rootwin_x_window(WRootWin *rootwin)
-{
- return WROOTWIN_ROOT(rootwin);
-}
-
-
/*}}}*/
/*{{{ Misc */
-static bool scr_ok(WRegion *r)
-{
- return (OBJ_IS(r, WScreen) && REGION_IS_MAPPED(r));
-}
-
-
/*EXTL_DOC
* Returns previously active screen on root window \var{rootwin}.
*/
EXTL_EXPORT_MEMBER
WScreen *rootwin_current_scr(WRootWin *rootwin)
{
- WRegion *r=REGION_ACTIVE_SUB(rootwin);
- WScreen *scr;
-
- /* There should be no non-WScreen as children or managed by us, but... */
-
- if(r!=NULL && scr_ok(r))
- return (WScreen*)r;
+ WScreen *scr, *fb=NULL;
FOR_ALL_SCREENS(scr){
- if(REGION_MANAGER(scr)==(WRegion*)rootwin
- && REGION_IS_MAPPED(scr)){
- break;
+ if(REGION_MANAGER(scr)==(WRegion*)rootwin && REGION_IS_MAPPED(scr)){
+ fb=scr;
+ if(REGION_IS_ACTIVE(scr))
+ return scr;
}
}
- return scr;
+ return (fb ? fb : &rootwin->scr);
}
static DynFunTab rootwin_dynfuntab[]={
{region_map, rootwin_map},
{region_unmap, rootwin_unmap},
- {region_do_set_focus, rootwin_do_set_focus},
- {(DynFun*)region_xwindow, (DynFun*)rootwin_x_window},
{(DynFun*)region_fitrep, (DynFun*)rootwin_fitrep},
- {region_managed_remove, rootwin_managed_remove},
END_DYNFUNTAB
};
EXTL_EXPORT
-IMPLCLASS(WRootWin, WWindow, rootwin_deinit, rootwin_dynfuntab);
+IMPLCLASS(WRootWin, WScreen, rootwin_deinit, rootwin_dynfuntab);
/*}}}*/