4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
9 #include <libtu/objp.h>
10 #include <libextl/extl.h>
16 #include "fullscreen.h"
29 WScreen *clientwin_find_suitable_screen(WClientWin *cwin,
30 const WManageParams *param)
32 WScreen *scr=NULL, *found=NULL;
33 bool respectpos=(param->tfor!=NULL || param->userpos);
36 if(!region_same_rootwin((WRegion*)scr, (WRegion*)cwin))
39 if(!OBJ_IS(scr, WRootWin)){
40 /* The root window itself is only a fallback */
42 if(REGION_IS_ACTIVE(scr)){
48 if(rectangle_contains(®ION_GEOM(scr),
49 param->geom.x, param->geom.y)){
64 /*extern WRegion *ioncore_newly_created;*/
67 static WPHolder *try_target(WClientWin *cwin, const WManageParams *param,
70 WRegion *r=ioncore_lookup_region(target, NULL);
75 return region_prepare_manage(r, cwin, param, MANAGE_PRIORITY_NONE);
79 static bool handle_target_winprops(WClientWin *cwin, const WManageParams *param,
80 WScreen *scr, WPHolder **ph_ret)
82 char *layout=NULL, *target=NULL;
86 if(extl_table_gets_s(cwin->proptab, "target", &target))
87 ph=try_target(cwin, param, target);
89 if(ph==NULL && extl_table_gets_s(cwin->proptab, "new_group", &layout)){
90 ExtlTab lo=ioncore_get_layout(layout);
94 if(lo!=extl_table_none()){
95 WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
96 int mask=MPLEX_ATTACH_SWITCHTO;
100 par.flags|=MPLEX_ATTACH_SWITCHTO;
102 /*ioncore_newly_created=(WRegion*)cwin;*/
104 reg=mplex_attach_new_(&scr->mplex, &par, mask, lo);
106 extl_unref_table(lo);
108 /*ioncore_newly_created=NULL;*/
110 mgd=(region_manager((WRegion*)cwin)!=NULL);
112 if(reg!=NULL && !mgd){
114 ph=try_target(cwin, param, target);
117 ph=region_prepare_manage(reg, cwin, param,
118 MANAGE_PRIORITY_NONE);
121 destroy_obj((Obj*)reg);
136 static bool try_fullscreen(WClientWin *cwin, WScreen *dflt,
137 const WManageParams *param)
139 WScreen *fs_scr=NULL;
142 /* Check fullscreen mode. (This is intentionally not done
143 * for transients and windows with target winprops.)
145 if(extl_table_gets_b(cwin->proptab, "fullscreen", &tmp)){
152 fs_scr=netwm_check_initial_fullscreen(cwin);
155 fs_scr=clientwin_fullscreen_chkrq(cwin, param->geom.w, param->geom.h);
158 WPHolder *fs_ph=region_prepare_manage((WRegion*)fs_scr, cwin, param,
159 MANAGE_PRIORITY_NOREDIR);
162 int swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
164 cwin->flags|=CLIENTWIN_FS_RQ;
166 fs=pholder_attach(fs_ph, swf, (WRegion*)cwin);
169 cwin->flags&=~CLIENTWIN_FS_RQ;
171 destroy_obj((Obj*)fs_ph);
179 bool clientwin_do_manage_default(WClientWin *cwin,
180 const WManageParams *param)
184 int swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
187 /* Find a suitable screen */
188 scr=clientwin_find_suitable_screen(cwin, param);
190 warn(TR("Unable to find a screen for a new client window."));
194 if(handle_target_winprops(cwin, param, scr, &ph))
197 /* Check if param->tfor or any of its managers want to manage cwin. */
198 if(ph==NULL && param->tfor!=NULL){
199 assert(param->tfor!=cwin);
200 ph=region_prepare_manage_transient((WRegion*)param->tfor, cwin,
206 /* Find a placeholder for non-fullscreen state */
207 ph=region_prepare_manage((WRegion*)scr, cwin, param,
208 MANAGE_PRIORITY_NONE);
210 if(try_fullscreen(cwin, scr, param)){
211 if(pholder_target(ph)!=(WRegion*)region_screen_of((WRegion*)cwin)){
212 WRegion *grp=region_groupleader_of((WRegion*)cwin);
213 if(region_do_set_return(grp, ph))
216 destroy_obj((Obj*)ph);
225 /* Not in full-screen mode; use the placeholder to attach. */
227 ok=pholder_attach(ph, swf, (WRegion*)cwin);
229 destroy_obj((Obj*)ph);
232 ioncore_unsqueeze((WRegion*)cwin, FALSE);
241 /*{{{ region_prepare_manage/region_manage_clientwin/etc. */
244 WPHolder *region_prepare_manage(WRegion *reg, const WClientWin *cwin,
245 const WManageParams *param, int priority)
248 CALL_DYN_RET(ret, WPHolder*, region_prepare_manage, reg,
249 (reg, cwin, param, priority));
254 WPHolder *region_prepare_manage_default(WRegion *reg, const WClientWin *cwin,
255 const WManageParams *param, int priority)
257 int cpriority=MANAGE_PRIORITY_SUB(priority, MANAGE_PRIORITY_NONE);
258 WRegion *curr=region_current(reg);
263 return region_prepare_manage(curr, cwin, param, cpriority);
267 WPHolder *region_prepare_manage_transient(WRegion *reg,
268 const WClientWin *cwin,
269 const WManageParams *param,
273 CALL_DYN_RET(ret, WPHolder*, region_prepare_manage_transient, reg,
274 (reg, cwin, param, unused));
279 WPHolder *region_prepare_manage_transient_default(WRegion *reg,
280 const WClientWin *cwin,
281 const WManageParams *param,
284 WRegion *mgr=REGION_MANAGER(reg);
287 return region_prepare_manage_transient(mgr, cwin, param, unused);
293 bool region_manage_clientwin(WRegion *reg, WClientWin *cwin,
294 const WManageParams *par, int priority)
297 WPHolder *ph=region_prepare_manage(reg, cwin, par, priority);
298 int swf=(par->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
303 ret=pholder_attach(ph, swf, (WRegion*)cwin);
305 destroy_obj((Obj*)ph);
317 DECLSTRUCT(WRescueInfo){
326 static WRegion *iter_children(void *st)
328 WRegion **nextp=(WRegion**)st;
329 WRegion *next=*nextp;
330 *nextp=(next==NULL ? NULL : next->p_next);
335 bool region_rescue_child_clientwins(WRegion *reg, WRescueInfo *info)
337 WRegion *next=reg->children;
338 return region_rescue_some_clientwins(reg, info, iter_children, &next);
342 /* Bah, unsplitissä oikestaan pitäisi tehä non-deep rescue */
344 bool region_do_rescue_this(WRegion *tosave_, WRescueInfo *info, int ph_flags)
346 WClientWin *cwin=OBJ_CAST(tosave_, WClientWin);
347 WRegion *tosave=NULL;
350 if(cwin->flags&CLIENTWIN_UNMAP_RQ)
352 tosave=(WRegion*)cwin;
353 }else if(info->flags®ION_RESCUE_NODEEP){
356 /* Try to rescue whole groups. */
357 /*tosave=(WRegion*)OBJ_CAST(tosave_, WGroupCW);*/
361 return region_rescue_clientwins(tosave_, info);
362 }else if(info->test){
365 int phf=(info->flags®ION_RESCUE_PHFLAGS_OK ? ph_flags : 0);
368 info->ph=region_get_rescue_pholder(info->get_rescue);
370 info->failed_get=TRUE;
374 return pholder_attach(info->ph, phf, tosave);
379 bool region_rescue_some_clientwins(WRegion *reg, WRescueInfo *info,
380 WRegionIterator *iter, void *st)
388 reg->flags|=REGION_CWINS_BEING_RESCUED;
391 WRegion *tosave=iter(st);
396 if(!region_do_rescue_this(tosave, info, 0)){
403 reg->flags&=~REGION_CWINS_BEING_RESCUED;
405 return (fails==0 && !info->failed_get);
409 bool region_rescue_clientwins(WRegion *reg, WRescueInfo *info)
412 CALL_DYN_RET(ret, bool, region_rescue_clientwins, reg, (reg, info));
417 bool region_rescue(WRegion *reg, WPHolder *ph, int flags)
426 info.failed_get=FALSE;
428 ret=region_rescue_clientwins(reg, &info);
431 destroy_obj((Obj*)info.ph);
437 bool region_rescue_needed(WRegion *reg)
445 info.failed_get=FALSE;
447 return !region_rescue_clientwins(reg, &info);
457 ExtlTab manageparams_to_table(const WManageParams *mp)
459 ExtlTab t=extl_create_table();
460 extl_table_sets_b(t, "switchto", mp->switchto);
461 extl_table_sets_b(t, "jumpto", mp->jumpto);
462 extl_table_sets_b(t, "userpos", mp->userpos);
463 extl_table_sets_b(t, "dockapp", mp->dockapp);
464 extl_table_sets_b(t, "maprq", mp->maprq);
465 extl_table_sets_i(t, "gravity", mp->gravity);
466 extl_table_sets_rectangle(t, "geom", &(mp->geom));
467 extl_table_sets_o(t, "tfor", (Obj*)(mp->tfor));