X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fclientwin.c;h=11ce2904b56c7d085c5a2924b2b596fa77fbd2f8;hp=4a5b4dacfd40ae08492058395d0d826df1b6c6dc;hb=HEAD;hpb=768d45580fc176cedd04db0b05621cdf596751d5 diff --git a/ioncore/clientwin.c b/ioncore/clientwin.c index 4a5b4da..11ce290 100644 --- a/ioncore/clientwin.c +++ b/ioncore/clientwin.c @@ -1,12 +1,9 @@ /* * ion/ioncore/clientwin.c * - * Copyright (c) Tuomo Valkonen 1999-2007. + * 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 @@ -124,6 +121,7 @@ static WSizePolicy get_sizepolicy_winprop(WClientWin *cwin, static void clientwin_get_winprops(WClientWin *cwin) { ExtlTab tab, tab2; + char *s; int i1, i2; tab=ioncore_get_winprop(cwin); @@ -157,13 +155,13 @@ static void clientwin_get_winprops(WClientWin *cwin) if(extl_table_is_bool_set(tab, "ignore_cfgrq")) cwin->flags|=CLIENTWIN_PROP_IGNORE_CFGRQ; -#if 0 - cwin->szplcy=get_sizepolicy_winprop(cwin, "sizepolicy", - SIZEPOLICY_DEFAULT); - cwin->transient_szplcy=get_sizepolicy_winprop(cwin, - "transient_sizepolicy", - DFLT_SZPLCY); -#endif + if(extl_table_gets_s(tab, "orientation", &s)){ + if(strcmp(s, "vertical")==0) + cwin->flags|=CLIENTWIN_PROP_O_VERT; + else if(strcmp(s, "horizontal")==0) + cwin->flags|=CLIENTWIN_PROP_O_HORIZ; + free(s); + } } @@ -323,8 +321,6 @@ static bool clientwin_init(WClientWin *cwin, WWindow *par, Window win, set_sane_gravity(cwin->win); - cwin->transient_for=None; - cwin->n_cmapwins=0; cwin->cmap=attr->colormap; cwin->cmaps=NULL; @@ -452,7 +448,6 @@ WClientWin* ioncore_manage_clientwin(Window win, bool maprq) param.dockapp=FALSE; -again: /* Is the window already being managed? */ cwin=XWINDOW_REGION_OF_T(win, WClientWin); if(cwin!=NULL) @@ -463,51 +458,88 @@ again: */ xwindow_unmanaged_selectinput(win, StructureNotifyMask); + if(!XGetWindowAttributes(ioncore_g.dpy, win, &attr)){ + if(maprq) + warn(TR("Window %#x disappeared."), win); + goto fail2; + } /* Is it a dockapp? */ hints=XGetWMHints(ioncore_g.dpy, win); - - if(hints!=NULL && hints->flags&StateHint) - init_state=hints->initial_state; - if(!param.dockapp && init_state==WithdrawnState && - hints->flags&IconWindowHint && hints->icon_window!=None){ - /* The dockapp might be displaying its "main" window if no - * wm that understands dockapps has been managing it. - */ - if(!maprq) - XUnmapWindow(ioncore_g.dpy, win); - - xwindow_unmanaged_selectinput(win, 0); - - win=hints->icon_window; - - /* It is a dockapp, do everything again from the beginning, now - * with the icon window. - */ - param.dockapp=TRUE; - goto again; - } + if(hints!=NULL){ + if(hints->flags&StateHint) + init_state=hints->initial_state; - if(hints!=NULL) - XFree((void*)hints); + if(!param.dockapp && init_state==WithdrawnState && + hints->flags&IconWindowHint && hints->icon_window!=None){ + Window icon_win=hints->icon_window; + XWindowAttributes icon_attr; + + if(!XGetWindowAttributes(ioncore_g.dpy, icon_win, &icon_attr)){ + if(maprq) + warn(TR("Window %#x disappeared."), win); + XFree((void*)hints); + goto fail2; + } + + if(!maprq){ + if(attr.map_state==IsViewable){ + /* The dockapp might be displaying its "main" window if no + * wm that understands dockapps has been managing it. + */ + XUnmapWindow(ioncore_g.dpy, win); + param.dockapp=TRUE; + }else{ + /* Main window is unmapped on initial scan, but icon window + * is mapped. Let's hope it's a dockapp left by e.g. us. + */ + if(icon_attr.map_state==IsViewable) + param.dockapp=TRUE; + } + }else{ + param.dockapp=TRUE; + } - if(!XGetWindowAttributes(ioncore_g.dpy, win, &attr)){ - if(maprq) - warn(TR("Window %#x disappeared."), win); - goto fail2; + if(param.dockapp){ + char **p=NULL; + int n=0; + + xwindow_unmanaged_selectinput(win, 0); + xwindow_unmanaged_selectinput(icon_win, StructureNotifyMask); + + /* Copy WM_CLASS as _ION_DOCKAPP_HACK */ + + p=xwindow_get_text_property(win, XA_WM_CLASS, &n); + + if(p!=NULL){ + xwindow_set_text_property(icon_win, ioncore_g.atom_dockapp_hack, + (const char **)p, n); + XFreeStringList(p); + }else{ + const char *pdummy[2]={"unknowndockapp", "UnknownDockapp"}; + xwindow_set_text_property(icon_win, ioncore_g.atom_dockapp_hack, + pdummy, 2); + } + + win=icon_win; + attr=icon_attr; + } + } + + XFree((void*)hints); } - attr.width=maxof(attr.width, 1); - attr.height=maxof(attr.height, 1); - /* Do we really want to manage it? */ if(!param.dockapp && (attr.override_redirect || (!maprq && attr.map_state!=IsViewable))){ goto fail2; } + attr.width=maxof(attr.width, 1); + attr.height=maxof(attr.height, 1); + /* Find root window */ FOR_ALL_ROOTWINS(rootwin){ if(WROOTWIN_ROOT(rootwin)==attr.root) @@ -529,8 +561,9 @@ again: param.geom=REGION_GEOM(cwin); param.maprq=maprq; - param.switchto=(init_state!=IconicState && clientwin_get_switchto(cwin)); param.jumpto=extl_table_is_bool_set(cwin->proptab, "jumpto"); + param.switchto=(init_state!=IconicState && + (param.jumpto || clientwin_get_switchto(cwin))); param.gravity=(cwin->size_hints.flags&PWinGravity ? cwin->size_hints.win_gravity : ForgetGravity); @@ -565,7 +598,11 @@ again: } if(postmanage_check(cwin, &attr)){ - if(param.jumpto && ioncore_g.focus_next==NULL) + /* Check for focus_next==NULL does not play nicely with + * pointer_focus_hack. + */ + /*if(param.jumpto && ioncore_g.focus_next==NULL)*/ + if(param.jumpto && !region_manager_is_focusnext((WRegion*)cwin)) region_goto((WRegion*)cwin); hook_call_o(clientwin_mapped_hook, (Obj*)cwin); return cwin; @@ -754,8 +791,8 @@ static bool send_clientmsg(Window win, Atom a, Time stmp) /*EXTL_DOC - * Attempt to kill (with XKillWindow) the client that owns the X - * window correspoding to \var{cwin}. + * Attempt to kill (with \code{XKillWindow}) the client that owns + * the X window correspoding to \var{cwin}. */ EXTL_EXPORT_MEMBER void clientwin_kill(WClientWin *cwin) @@ -1025,6 +1062,16 @@ static void clientwin_size_hints(WClientWin *cwin, WSizeHints *hints_ret) } +static int clientwin_orientation(WClientWin *cwin) +{ + return (cwin->flags&CLIENTWIN_PROP_O_VERT + ? REGION_ORIENTATION_VERTICAL + : (cwin->flags&CLIENTWIN_PROP_O_HORIZ + ? REGION_ORIENTATION_HORIZONTAL + : REGION_ORIENTATION_NONE)); +} + + /*}}}*/ @@ -1041,12 +1088,27 @@ EXTL_SAFE EXTL_EXPORT_MEMBER ExtlTab clientwin_get_ident(WClientWin *cwin) { - char **p=NULL, *wrole=NULL; + char **p=NULL, **p2=NULL, *wrole=NULL; int n=0, n2=0, n3=0, tmp=0; + Window tforwin=None; ExtlTab tab; + bool dockapp_hack=FALSE; p=xwindow_get_text_property(cwin->win, XA_WM_CLASS, &n); - wrole=xwindow_get_string_property(cwin->win, ioncore_g.atom_wm_window_role, &n2); + + p2=xwindow_get_text_property(cwin->win, ioncore_g.atom_dockapp_hack, &n2); + + dockapp_hack=(n2>0); + + if(p==NULL){ + /* Some dockapps do actually have WM_CLASS, so use it. */ + p=p2; + n=n2; + p2=NULL; + } + + wrole=xwindow_get_string_property(cwin->win, ioncore_g.atom_wm_window_role, + &n3); tab=extl_create_table(); if(n>=2 && p[1]!=NULL) @@ -1056,8 +1118,18 @@ ExtlTab clientwin_get_ident(WClientWin *cwin) if(wrole!=NULL) extl_table_sets_s(tab, "role", wrole); + if(XGetTransientForHint(ioncore_g.dpy, cwin->win, &tforwin) + && tforwin!=None){ + extl_table_sets_b(tab, "is_transient", TRUE); + } + + if(dockapp_hack) + extl_table_sets_b(tab, "is_dockapp", TRUE); + if(p!=NULL) XFreeStringList(p); + if(p2!=NULL) + XFreeStringList(p2); if(wrole!=NULL) free(wrole); @@ -1085,9 +1157,9 @@ static bool check_fs_cfgrq(WClientWin *cwin, XConfigureRequestEvent *ev) if(!region_fullscreen_scr(grp, scr, sw)) cwin->flags&=~CLIENTWIN_FS_RQ; + + return TRUE; } - - return TRUE; } return FALSE; @@ -1252,6 +1324,25 @@ static ExtlTab clientwin_get_configuration(WClientWin *cwin) } +static void do_sm(ExtlTab tab) +{ + SMAddCallback *add_cb; + SMCfgCallback *cfg_cb; + WPHolder *ph; + + ioncore_get_sm_callbacks(&add_cb, &cfg_cb); + + if(add_cb!=NULL){ + ph=ioncore_get_load_pholder(); + + if(ph!=NULL){ + if(!add_cb(ph, tab)) + destroy_obj((Obj*)ph); + } + } +} + + WRegion *clientwin_load(WWindow *par, const WFitParams *fp, ExtlTab tab) { double wind=0; @@ -1260,8 +1351,8 @@ WRegion *clientwin_load(WWindow *par, const WFitParams *fp, ExtlTab tab) WClientWin *cwin=NULL; XWindowAttributes attr; WRectangle rg; - bool got_chkc; - + bool got_chkc=FALSE; + if(!extl_table_gets_d(tab, "windowid", &wind) || !extl_table_gets_i(tab, "checkcode", &chkc)){ return NULL; @@ -1278,7 +1369,7 @@ WRegion *clientwin_load(WWindow *par, const WFitParams *fp, ExtlTab tab) &real_chkc); if(!got_chkc || real_chkc!=chkc){ - ioncore_clientwin_load_missing(); + do_sm(tab); return NULL; } @@ -1289,19 +1380,15 @@ WRegion *clientwin_load(WWindow *par, const WFitParams *fp, ExtlTab tab) return NULL; } + if(attr.root!=region_root_of((WRegion*)par)) + return NULL; + if(attr.override_redirect || (ioncore_g.opmode==IONCORE_OPMODE_INIT && attr.map_state!=IsViewable)){ warn(TR("Saved client window does not want to be managed.")); return NULL; } - - /* - attr.x=fp->g.x; - attr.y=fp->g.y; - attr.width=fp->g.w; - attr.height=fp->g.h; - */ - + cwin=create_clientwin(par, win, &attr); if(cwin==NULL) @@ -1358,6 +1445,9 @@ static DynFunTab clientwin_dynfuntab[]={ {region_size_hints, clientwin_size_hints}, + + {(DynFun*)region_orientation, + (DynFun*)clientwin_orientation}, {(DynFun*)region_rqclose, (DynFun*)clientwin_rqclose},