X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fscreen.c;h=c16bfc2f79fec61d551b80497793eff6a0f1e65d;hp=3b896bfab6e218012b041d6a11d2e4d12f81b626;hb=e3aec18706513a87eaa7839dfdaf7e0fcd0d8d2a;hpb=8366314611bf30a0f31d25bf5f5023186fa87692 diff --git a/ioncore/screen.c b/ioncore/screen.c index 3b896bf..c16bfc2 100644 --- a/ioncore/screen.c +++ b/ioncore/screen.c @@ -1,19 +1,15 @@ /* * ion/ioncore/screen.c * - * Copyright (c) Tuomo Valkonen 1999-2006. + * Copyright (c) Tuomo Valkonen 1999-2009. * - * 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 #include #include -#include #include "common.h" #include "global.h" @@ -32,78 +28,75 @@ #include "regbind.h" #include "frame-pointer.h" #include "rectangle.h" -#include "infowin.h" -#include "activity.h" #include "extlconv.h" #include "llist.h" #include "group-ws.h" #include "mplex.h" -#include "tags.h" +#include "conf.h" +#include "activity.h" +#include "screen-notify.h" WHook *screen_managed_changed_hook=NULL; -static void screen_update_infowin(WScreen *scr); - - - /*{{{ Init/deinit */ -static bool screen_init(WScreen *scr, WRootWin *rootwin, - int id, const WFitParams *fp, bool useroot) +bool screen_init(WScreen *scr, WRootWin *parent, + const WFitParams *fp, int id, Window rootwin) { Window win; XSetWindowAttributes attr; ulong attrflags=0; + bool is_root=FALSE; scr->id=id; scr->atom_workspace=None; - scr->uses_root=useroot; scr->managed_off.x=0; scr->managed_off.y=0; scr->managed_off.w=0; scr->managed_off.h=0; scr->next_scr=NULL; scr->prev_scr=NULL; - scr->rotation=SCREEN_ROTATION_0; watch_init(&(scr->notifywin_watch)); watch_init(&(scr->infowin_watch)); - if(useroot){ - win=WROOTWIN_ROOT(rootwin); + if(parent==NULL){ + win=rootwin; + is_root=TRUE; }else{ attr.background_pixmap=ParentRelative; attrflags=CWBackPixmap; - win=XCreateWindow(ioncore_g.dpy, WROOTWIN_ROOT(rootwin), + win=XCreateWindow(ioncore_g.dpy, WROOTWIN_ROOT(parent), fp->g.x, fp->g.y, fp->g.w, fp->g.h, 0, - DefaultDepth(ioncore_g.dpy, rootwin->xscr), + DefaultDepth(ioncore_g.dpy, parent->xscr), InputOutput, - DefaultVisual(ioncore_g.dpy, rootwin->xscr), + DefaultVisual(ioncore_g.dpy, parent->xscr), attrflags, &attr); if(win==None) return FALSE; + } - if(!mplex_do_init((WMPlex*)scr, (WWindow*)rootwin, win, fp, FALSE)) + if(!mplex_do_init((WMPlex*)scr, (WWindow*)parent, fp, win)){ + if(!is_root) + XDestroyWindow(ioncore_g.dpy, win); return FALSE; + } /*scr->mplex.win.region.rootwin=rootwin; region_set_parent((WRegion*)scr, (WRegion*)rootwin);*/ scr->mplex.flags|=MPLEX_ADD_TO_END; scr->mplex.win.region.flags|=REGION_BINDINGS_ARE_GRABBED; - if(useroot) + + if(!is_root){ scr->mplex.win.region.flags|=REGION_MAPPED; + window_select_input((WWindow*)scr, IONCORE_EVENTMASK_SCREEN); + } - window_select_input(&(scr->mplex.win), - FocusChangeMask|EnterWindowMask| - KeyPressMask|KeyReleaseMask| - ButtonPressMask|ButtonReleaseMask| - (useroot ? IONCORE_EVENTMASK_ROOT : 0)); - if(id==0){ scr->atom_workspace=XInternAtom(ioncore_g.dpy, "_ION_WORKSPACE", False); @@ -116,10 +109,12 @@ static bool screen_init(WScreen *scr, WRootWin *rootwin, } } - /* Add rootwin's bindings to screens (ungrabbed) so that bindings - * are called with the proper region. + /* Add all the needed bindings here; mplex does nothing so that + * frames don't have to remove extra bindings. */ - region_add_bindmap((WRegion*)scr, ioncore_rootwin_bindmap); + region_add_bindmap((WRegion*)scr, ioncore_screen_bindmap); + region_add_bindmap((WRegion*)scr, ioncore_mplex_bindmap); + region_add_bindmap((WRegion*)scr, ioncore_mplex_toplevel_bindmap); LINK_ITEM(ioncore_g.screens, scr, next_scr, prev_scr); @@ -127,10 +122,9 @@ static bool screen_init(WScreen *scr, WRootWin *rootwin, } -WScreen *create_screen(WRootWin *rootwin, int id, const WFitParams *fp, - bool useroot) +WScreen *create_screen(WRootWin *parent, const WFitParams *fp, int id) { - CREATEOBJ_IMPL(WScreen, screen, (p, rootwin, id, fp, useroot)); + CREATEOBJ_IMPL(WScreen, screen, (p, parent, fp, id, None)); } @@ -138,9 +132,6 @@ void screen_deinit(WScreen *scr) { UNLINK_ITEM(ioncore_g.screens, scr, next_scr, prev_scr); - if(scr->uses_root) - scr->mplex.win.win=None; - mplex_deinit((WMPlex*)scr); } @@ -221,6 +212,9 @@ static void screen_managed_changed(WScreen *scr, int mode, bool sw, n==NULL ? "" : n); } + if(region_is_activity_r((WRegion*)scr)) + screen_update_notifywin(scr); + screen_update_infowin(scr); mplex_call_changed_hook((WMPlex*)scr, @@ -259,190 +253,11 @@ void screen_activated(WScreen *scr) /*}}}*/ -/*}}}*/ - - -/*{{{ Notifications */ - - -static void do_notify(WScreen *scr, Watch *watch, bool right, - const char *str, - char *style, const char *attr) -{ - - WInfoWin *iw=(WInfoWin*)(watch->obj); - WFitParams fp; - - if(iw==NULL){ - WMPlexAttachParams param=MPLEXATTACHPARAMS_INIT; - - param.flags=(MPLEX_ATTACH_UNNUMBERED| - MPLEX_ATTACH_SIZEPOLICY| - MPLEX_ATTACH_GEOM| - MPLEX_ATTACH_LEVEL); - param.level=STACKING_LEVEL_ON_TOP; - - if(!right){ - param.szplcy=SIZEPOLICY_GRAVITY_NORTHWEST; - param.geom.x=0; - }else{ - param.szplcy=SIZEPOLICY_GRAVITY_NORTHEAST; - param.geom.x=REGION_GEOM(scr).w-1; - } - - param.geom.y=0; - param.geom.w=1; - param.geom.h=1; - - iw=(WInfoWin*)mplex_do_attach_new(&scr->mplex, ¶m, - (WRegionCreateFn*)create_infowin, - style); - - if(iw==NULL) - return; - - watch_setup(watch, (Obj*)iw, NULL); - } - - infowin_set_attr2(iw, attr, NULL); - infowin_set_text(iw, str); -} - - -void screen_notify(WScreen *scr, const char *str) -{ - do_notify(scr, &scr->notifywin_watch, FALSE, str, "actnotify", NULL); -} - - -void screen_windowinfo(WScreen *scr, const char *str, const char *attr) -{ - do_notify(scr, &scr->infowin_watch, TRUE, str, "tab-info", attr); -} - - -void screen_unnotify(WScreen *scr) -{ - Obj *iw=scr->notifywin_watch.obj; - if(iw!=NULL){ - watch_reset(&(scr->notifywin_watch)); - mainloop_defer_destroy(iw); - } -} - - -void screen_nowindowinfo(WScreen *scr) -{ - Obj *iw=scr->infowin_watch.obj; - if(iw!=NULL){ - watch_reset(&(scr->infowin_watch)); - mainloop_defer_destroy(iw); - } -} - - -static char *addnot(char *str, WRegion *reg) -{ - const char *nm=region_name(reg); - char *nstr=NULL; - - if(nm==NULL) - return str; - - if(str==NULL) - return scat(TR("act: "), nm); - - nstr=scat3(str, ", ", nm); - if(nstr!=NULL) - free(str); - return nstr; -} - - -static char *screen_managed_activity(WScreen *scr) -{ - char *notstr=NULL; - WMPlexIterTmp tmp; - WRegion *reg; - - FOR_ALL_MANAGED_BY_MPLEX(&scr->mplex, reg, tmp){ - if(region_is_activity_r(reg) && !REGION_IS_MAPPED(reg)) - notstr=addnot(notstr, reg); - } - - return notstr; -} - - -static void screen_notify_activity(WScreen *scr) -{ - if(ioncore_g.screen_notify){ - char *notstr=screen_managed_activity(scr); - if(notstr!=NULL){ - screen_notify(scr, notstr); - free(notstr); - return; - } - } - - screen_unnotify(scr); - - screen_update_infowin(scr); -} - - -static void screen_notify_tag(WScreen *scr) -{ - screen_update_infowin(scr); -} - - -static void screen_update_infowin(WScreen *scr) -{ - WRegion *reg=mplex_mx_current(&(scr->mplex)); - bool tag=(reg!=NULL && region_is_tagged(reg)); - bool act=(reg!=NULL && region_is_activity_r(reg)); - - if(tag || act){ - const char *n=region_displayname(reg); - char *attr=NULL; - - libtu_asprintf(&attr, "%s-selected-%s-not_dragged-%s", - (REGION_IS_ACTIVE(scr) ? "active" : "inactive"), - (tag ? "tagged" : "not_tagged"), - (act ? "activity" : "no_activity")); - - screen_windowinfo(scr, n, attr); /* NULL attr ok */ - }else{ - screen_nowindowinfo(scr); - } -} - - -static void screen_managed_notify(WScreen *scr, WRegion *reg, const char *how) -{ - if(strcmp(how, "sub-activity")==0){ - /* TODO: multiple calls */ - mainloop_defer_action((Obj*)scr, - (WDeferredAction*)screen_notify_activity); - }else if(strcmp(how, "tag")==0){ - mainloop_defer_action((Obj*)scr, - (WDeferredAction*)screen_notify_tag); - } -} - - -/*}}}*/ - - /*{{{ Misc. */ /*EXTL_DOC - * Find the screen with numerical id \var{id}. If Xinerama is - * not present, \var{id} corresponds to X screen numbers. Otherwise - * the ids are some arbitrary ordering of Xinerama rootwins. - * If \var{id} is $-1$, the screen with the highest id is returned. + * Find the screen with numerical id \var{id}. */ EXTL_SAFE EXTL_EXPORT @@ -547,32 +362,33 @@ int screen_id(WScreen *scr) } -static bool screen_managed_may_destroy(WScreen *scr, WRegion *reg) +static WRegion *screen_managed_disposeroot(WScreen *scr, WRegion *reg) { - bool onmxlist=FALSE; + bool onmxlist=FALSE, others=FALSE; WLListNode *lnode; WLListIterTmp tmp; - - if(OBJ_IS(reg, WClientWin)) - return TRUE; - FOR_ALL_NODES_ON_LLIST(lnode, scr->mplex.mx_list, tmp){ - if(lnode->st->reg==reg) - onmxlist=TRUE; - else /*if(OBJ_IS(node->reg, WGenWS))*/ - return TRUE; + if(OBJ_IS(reg, WGroupWS)){ + FOR_ALL_NODES_ON_LLIST(lnode, scr->mplex.mx_list, tmp){ + if(lnode->st->reg==reg){ + onmxlist=TRUE; + }else if(OBJ_IS(lnode->st->reg, WGroupWS)){ + others=TRUE; + break; + } + } + + if(onmxlist && !others){ + warn(TR("Only workspace may not be destroyed/detached.")); + return NULL; + } } - if(!onmxlist) - return TRUE; - - warn(TR("Only workspace may not be destroyed.")); - - return FALSE; + return reg; } -static bool screen_may_destroy(WScreen *scr) +static bool screen_may_dispose(WScreen *scr) { warn(TR("Screens may not be destroyed.")); return FALSE; @@ -615,13 +431,6 @@ err: } -WPHolder *screen_get_rescue_pholder_for(WScreen *scr, WRegion *mgd) -{ -#warning "TODO: better special case handling for groups" - - return (WPHolder*)mplex_get_rescue_pholder_for(&(scr->mplex), mgd); -} - /*}}}*/ @@ -644,13 +453,16 @@ static WRegion *do_create_initial(WWindow *parent, const WFitParams *fp, static bool create_initial_ws(WScreen *scr) { WRegion *reg=NULL; - WMPlexAttachParams par; - - par.flags=0; + WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT; + ExtlTab lo=ioncore_get_layout("default"); - reg=mplex_do_attach_new(&scr->mplex, &par, - (WRegionCreateFn*)groupws_load_default, - NULL); + if(lo==extl_table_none()){ + reg=mplex_do_attach_new(&scr->mplex, &par, + (WRegionCreateFn*)create_groupws, NULL); + }else{ + reg=mplex_attach_new_(&scr->mplex, &par, 0, lo); + extl_unref_table(lo); + } if(reg==NULL){ warn(TR("Unable to create a workspace on screen %d."), scr->id); @@ -694,11 +506,11 @@ static DynFunTab screen_dynfuntab[]={ {region_inactivated, screen_inactivated}, - {(DynFun*)region_managed_may_destroy, - (DynFun*)screen_managed_may_destroy}, + {(DynFun*)region_managed_disposeroot, + (DynFun*)screen_managed_disposeroot}, - {(DynFun*)region_may_destroy, - (DynFun*)screen_may_destroy}, + {(DynFun*)region_may_dispose, + (DynFun*)screen_may_dispose}, {mplex_managed_changed, screen_managed_changed}, @@ -718,9 +530,6 @@ static DynFunTab screen_dynfuntab[]={ {(DynFun*)region_fitrep, (DynFun*)screen_fitrep}, - {(DynFun*)region_get_rescue_pholder_for, - (DynFun*)screen_get_rescue_pholder_for}, - END_DYNFUNTAB };