4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
12 #include <libtu/objp.h>
13 #include <libextl/extl.h>
19 #include "fullscreen.h"
32 WScreen *clientwin_find_suitable_screen(WClientWin *cwin,
33 const WManageParams *param)
35 WScreen *scr=NULL, *found=NULL;
36 bool respectpos=(param->tfor!=NULL || param->userpos);
39 if(!region_same_rootwin((WRegion*)scr, (WRegion*)cwin))
42 if(!OBJ_IS(scr, WRootWin)){
43 /* The root window itself is only a fallback */
45 if(REGION_IS_ACTIVE(scr)){
51 if(rectangle_contains(®ION_GEOM(scr),
52 param->geom.x, param->geom.y)){
67 /*extern WRegion *ioncore_newly_created;*/
70 static WPHolder *try_target(WClientWin *cwin, const WManageParams *param,
73 WRegion *r=ioncore_lookup_region(target, NULL);
78 return region_prepare_manage(r, cwin, param, MANAGE_REDIR_PREFER_NO);
82 static bool handle_target_winprops(WClientWin *cwin, const WManageParams *param,
83 WScreen *scr, WPHolder **ph_ret)
85 char *layout=NULL, *target=NULL;
89 if(extl_table_gets_s(cwin->proptab, "target", &target))
90 ph=try_target(cwin, param, target);
92 if(ph==NULL && extl_table_gets_s(cwin->proptab, "new_group", &layout)){
93 ExtlTab lo=ioncore_get_layout(layout);
97 if(lo!=extl_table_none()){
98 WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
99 int mask=MPLEX_ATTACH_SWITCHTO;
103 par.flags|=MPLEX_ATTACH_SWITCHTO;
105 /*ioncore_newly_created=(WRegion*)cwin;*/
107 reg=mplex_attach_new_(&scr->mplex, &par, mask, lo);
109 extl_unref_table(lo);
111 /*ioncore_newly_created=NULL;*/
113 mgd=(region_manager((WRegion*)cwin)!=NULL);
115 if(reg!=NULL && !mgd){
117 ph=try_target(cwin, param, target);
120 ph=region_prepare_manage(reg, cwin, param,
121 MANAGE_REDIR_PREFER_YES);
124 destroy_obj((Obj*)reg);
139 static bool try_fullscreen(WClientWin *cwin, WScreen *dflt,
140 const WManageParams *param)
142 WScreen *fs_scr=NULL;
145 /* Check fullscreen mode. (This is intentionally not done
146 * for transients and windows with target winprops.)
148 if(extl_table_gets_b(cwin->proptab, "fullscreen", &tmp)){
155 fs_scr=netwm_check_initial_fullscreen(cwin);
158 fs_scr=clientwin_fullscreen_chkrq(cwin, param->geom.w, param->geom.h);
161 WPHolder *fs_ph=region_prepare_manage((WRegion*)fs_scr, cwin, param,
162 MANAGE_REDIR_STRICT_NO);
165 int swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
167 cwin->flags|=CLIENTWIN_FS_RQ;
169 fs=pholder_attach(fs_ph, swf, (WRegion*)cwin);
172 cwin->flags&=~CLIENTWIN_FS_RQ;
174 destroy_obj((Obj*)fs_ph);
182 bool clientwin_do_manage_default(WClientWin *cwin,
183 const WManageParams *param)
187 int swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
190 /* Find a suitable screen */
191 scr=clientwin_find_suitable_screen(cwin, param);
193 warn(TR("Unable to find a screen for a new client window."));
197 if(handle_target_winprops(cwin, param, scr, &ph))
200 /* Check if param->tfor or any of its managers want to manage cwin. */
201 if(ph==NULL && param->tfor!=NULL){
202 assert(param->tfor!=cwin);
203 ph=region_prepare_manage_transient((WRegion*)param->tfor, cwin,
209 /* Find a placeholder for non-fullscreen state */
210 ph=region_prepare_manage((WRegion*)scr, cwin, param,
211 MANAGE_REDIR_PREFER_YES);
213 if(try_fullscreen(cwin, scr, param)){
214 if(pholder_target(ph)!=(WRegion*)region_screen_of((WRegion*)cwin)){
215 WRegion *grp=region_groupleader_of((WRegion*)cwin);
216 if(region_do_set_return(grp, ph))
219 destroy_obj((Obj*)ph);
228 /* Not in full-screen mode; use the placeholder to attach. */
230 ok=pholder_attach(ph, swf, (WRegion*)cwin);
232 destroy_obj((Obj*)ph);
235 ioncore_unsqueeze((WRegion*)cwin, FALSE);
244 /*{{{ region_prepare_manage/region_manage_clientwin/etc. */
247 WPHolder *region_prepare_manage(WRegion *reg, const WClientWin *cwin,
248 const WManageParams *param, int redir)
251 CALL_DYN_RET(ret, WPHolder*, region_prepare_manage, reg,
252 (reg, cwin, param, redir));
257 WPHolder *region_prepare_manage_default(WRegion *reg, const WClientWin *cwin,
258 const WManageParams *param, int redir)
262 if(redir==MANAGE_REDIR_STRICT_NO)
265 curr=region_current(reg);
270 return region_prepare_manage(curr, cwin, param, MANAGE_REDIR_PREFER_YES);
274 WPHolder *region_prepare_manage_transient(WRegion *reg,
275 const WClientWin *cwin,
276 const WManageParams *param,
280 CALL_DYN_RET(ret, WPHolder*, region_prepare_manage_transient, reg,
281 (reg, cwin, param, unused));
286 WPHolder *region_prepare_manage_transient_default(WRegion *reg,
287 const WClientWin *cwin,
288 const WManageParams *param,
291 WRegion *mgr=REGION_MANAGER(reg);
294 return region_prepare_manage_transient(mgr, cwin, param, unused);
300 bool region_manage_clientwin(WRegion *reg, WClientWin *cwin,
301 const WManageParams *par, int redir)
304 WPHolder *ph=region_prepare_manage(reg, cwin, par, redir);
305 int swf=(par->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
310 ret=pholder_attach(ph, swf, (WRegion*)cwin);
312 destroy_obj((Obj*)ph);
324 DECLSTRUCT(WRescueInfo){
332 static WRegion *iter_children(void *st)
334 WRegion **nextp=(WRegion**)st;
335 WRegion *next=*nextp;
336 *nextp=(next==NULL ? NULL : next->p_next);
341 bool region_rescue_child_clientwins(WRegion *reg, WRescueInfo *info)
343 WRegion *next=reg->children;
344 return region_rescue_some_clientwins(reg, info, iter_children, &next);
348 bool region_rescue_some_clientwins(WRegion *reg, WRescueInfo *info,
349 WRegionIterator *iter, void *st)
357 reg->flags|=REGION_CWINS_BEING_RESCUED;
360 WRegion *tosave=iter(st);
366 cwin=OBJ_CAST(tosave, WClientWin);
369 if(!region_rescue_clientwins(tosave, info)){
374 }else if(info->test){
377 }else if(!(cwin->flags&CLIENTWIN_UNMAP_RQ)){
379 info->ph=region_get_rescue_pholder(info->get_rescue);
381 info->failed_get=TRUE;
385 if(!pholder_attach(info->ph, 0, (WRegion*)cwin))
390 reg->flags&=~REGION_CWINS_BEING_RESCUED;
392 return (fails==0 && !info->failed_get);
396 bool region_rescue_clientwins(WRegion *reg, WRescueInfo *info)
399 CALL_DYN_RET(ret, bool, region_rescue_clientwins, reg, (reg, info));
404 bool region_rescue(WRegion *reg, WPHolder *ph_param)
412 info.failed_get=FALSE;
414 ret=region_rescue_clientwins(reg, &info);
416 if(info.ph!=ph_param)
417 destroy_obj((Obj*)info.ph);
423 bool region_rescue_needed(WRegion *reg)
430 info.failed_get=FALSE;
432 return !region_rescue_clientwins(reg, &info);
442 ExtlTab manageparams_to_table(const WManageParams *mp)
444 ExtlTab t=extl_create_table();
445 extl_table_sets_b(t, "switchto", mp->switchto);
446 extl_table_sets_b(t, "jumpto", mp->jumpto);
447 extl_table_sets_b(t, "userpos", mp->userpos);
448 extl_table_sets_b(t, "dockapp", mp->dockapp);
449 extl_table_sets_b(t, "maprq", mp->maprq);
450 extl_table_sets_i(t, "gravity", mp->gravity);
451 extl_table_sets_rectangle(t, "geom", &(mp->geom));
452 extl_table_sets_o(t, "tfor", (Obj*)(mp->tfor));