4 * Copyright (c) Tuomo Valkonen 1999-2009.
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
))
38 if(REGION_IS_ACTIVE(scr
)){
44 if(rectangle_contains(®ION_GEOM(scr
),
45 param
->geom
.x
, param
->geom
.y
)){
59 /*extern WRegion *ioncore_newly_created;*/
62 static WPHolder
*try_target(WClientWin
*cwin
, const WManageParams
*param
,
65 WRegion
*r
=ioncore_lookup_region(target
, NULL
);
70 if(!region_same_rootwin(r
, (WRegion
*)cwin
))
73 return region_prepare_manage(r
, cwin
, param
, MANAGE_PRIORITY_NONE
);
77 static bool handle_target_winprops(WClientWin
*cwin
, const WManageParams
*param
,
78 WScreen
*scr
, WPHolder
**ph_ret
)
80 char *layout
=NULL
, *target
=NULL
;
84 if(extl_table_gets_s(cwin
->proptab
, "target", &target
))
85 ph
=try_target(cwin
, param
, target
);
87 if(ph
==NULL
&& extl_table_gets_s(cwin
->proptab
, "new_group", &layout
)){
88 ExtlTab lo
=ioncore_get_layout(layout
);
92 if(lo
!=extl_table_none()){
93 WMPlexAttachParams par
=MPLEXATTACHPARAMS_INIT
;
94 int mask
=MPLEX_ATTACH_SWITCHTO
;
98 par
.flags
|=MPLEX_ATTACH_SWITCHTO
;
100 /*ioncore_newly_created=(WRegion*)cwin;*/
102 reg
=mplex_attach_new_(&scr
->mplex
, &par
, mask
, lo
);
104 extl_unref_table(lo
);
106 /*ioncore_newly_created=NULL;*/
108 mgd
=(region_manager((WRegion
*)cwin
)!=NULL
);
110 if(reg
!=NULL
&& !mgd
){
112 ph
=try_target(cwin
, param
, target
);
115 ph
=region_prepare_manage(reg
, cwin
, param
,
116 MANAGE_PRIORITY_NONE
);
119 destroy_obj((Obj
*)reg
);
134 static bool try_fullscreen(WClientWin
*cwin
, WScreen
*dflt
,
135 const WManageParams
*param
)
137 WScreen
*fs_scr
=NULL
;
140 /* Check fullscreen mode. (This is intentionally not done
141 * for transients and windows with target winprops.)
143 if(extl_table_gets_b(cwin
->proptab
, "fullscreen", &tmp
)){
149 if(fs_scr
==NULL
&& netwm_check_initial_fullscreen(cwin
))
153 fs_scr
=clientwin_fullscreen_chkrq(cwin
, param
->geom
.w
, param
->geom
.h
);
156 WPHolder
*fs_ph
=region_prepare_manage((WRegion
*)fs_scr
, cwin
, param
,
157 MANAGE_PRIORITY_NOREDIR
);
160 int swf
=(param
->switchto
? PHOLDER_ATTACH_SWITCHTO
: 0);
162 cwin
->flags
|=CLIENTWIN_FS_RQ
;
164 fs
=pholder_attach(fs_ph
, swf
, (WRegion
*)cwin
);
167 cwin
->flags
&=~CLIENTWIN_FS_RQ
;
169 destroy_obj((Obj
*)fs_ph
);
177 bool clientwin_do_manage_default(WClientWin
*cwin
,
178 const WManageParams
*param
)
182 int swf
=(param
->switchto
? PHOLDER_ATTACH_SWITCHTO
: 0);
184 WRegion
*createroot
=NULL
;
186 /* Find a suitable screen */
187 scr
=clientwin_find_suitable_screen(cwin
, param
);
189 warn(TR("Unable to find a screen for a new client window."));
193 if(handle_target_winprops(cwin
, param
, scr
, &ph
))
196 /* Check if param->tfor or any of its managers want to manage cwin. */
197 if(ph
==NULL
&& param
->tfor
!=NULL
){
198 assert(param
->tfor
!=cwin
);
199 ph
=region_prepare_manage_transient((WRegion
*)param
->tfor
, cwin
,
205 /* Find a placeholder for non-fullscreen state */
206 ph
=region_prepare_manage((WRegion
*)scr
, cwin
, param
,
207 MANAGE_PRIORITY_NONE
);
209 if(try_fullscreen(cwin
, scr
, param
)){
210 if(pholder_target(ph
)!=(WRegion
*)region_screen_of((WRegion
*)cwin
)){
211 WRegion
*grp
=region_groupleader_of((WRegion
*)cwin
);
212 if(region_do_set_return(grp
, ph
))
215 destroy_obj((Obj
*)ph
);
224 /* Not in full-screen mode; use the placeholder to attach. */
226 WRegionAttachData data
;
227 data
.type
=REGION_ATTACH_REPARENT
;
228 data
.u
.reg
=(WRegion
*)cwin
;
230 createroot
=pholder_do_attach(ph
,
231 swf
|PHOLDER_ATTACH_RETURN_CREATEROOT
,
235 destroy_obj((Obj
*)ph
);
237 if(uq
&& createroot
!=NULL
)
238 ioncore_unsqueeze(createroot
, FALSE
);
240 return (createroot
!=NULL
);
247 /*{{{ region_prepare_manage/region_manage_clientwin/etc. */
250 WPHolder
*region_prepare_manage(WRegion
*reg
, const WClientWin
*cwin
,
251 const WManageParams
*param
, int priority
)
254 CALL_DYN_RET(ret
, WPHolder
*, region_prepare_manage
, reg
,
255 (reg
, cwin
, param
, priority
));
260 WPHolder
*region_prepare_manage_default(WRegion
*reg
, const WClientWin
*cwin
,
261 const WManageParams
*param
, int priority
)
263 int cpriority
=MANAGE_PRIORITY_SUB(priority
, MANAGE_PRIORITY_NONE
);
264 WRegion
*curr
=region_current(reg
);
269 return region_prepare_manage(curr
, cwin
, param
, cpriority
);
273 WPHolder
*region_prepare_manage_transient(WRegion
*reg
,
274 const WClientWin
*cwin
,
275 const WManageParams
*param
,
279 CALL_DYN_RET(ret
, WPHolder
*, region_prepare_manage_transient
, reg
,
280 (reg
, cwin
, param
, unused
));
285 WPHolder
*region_prepare_manage_transient_default(WRegion
*reg
,
286 const WClientWin
*cwin
,
287 const WManageParams
*param
,
290 WRegion
*mgr
=REGION_MANAGER(reg
);
293 return region_prepare_manage_transient(mgr
, cwin
, param
, unused
);
299 bool region_manage_clientwin(WRegion
*reg
, WClientWin
*cwin
,
300 const WManageParams
*par
, int priority
)
303 WPHolder
*ph
=region_prepare_manage(reg
, cwin
, par
, priority
);
304 int swf
=(par
->switchto
? PHOLDER_ATTACH_SWITCHTO
: 0);
309 ret
=pholder_attach(ph
, swf
, (WRegion
*)cwin
);
311 destroy_obj((Obj
*)ph
);
323 DECLSTRUCT(WRescueInfo
){
326 /** set to TRUE when we fail to get a PHolder for this region. */
333 static WRegion
*iter_children(void *st
)
335 WRegion
**nextp
=(WRegion
**)st
;
336 WRegion
*next
=*nextp
;
337 *nextp
=(next
==NULL
? NULL
: next
->p_next
);
342 bool region_rescue_child_clientwins(WRegion
*reg
, WRescueInfo
*info
)
344 WRegion
*next
=reg
->children
;
345 return region_rescue_some_clientwins(reg
, info
, iter_children
, &next
);
349 WPHolder
*rescueinfo_pholder(WRescueInfo
*info
)
355 info
->ph
=region_get_rescue_pholder(info
->get_rescue
);
357 info
->failed_get
=TRUE
;
366 /* Bah, unsplitissä oikestaan pitäisi tehä non-deep rescue */
368 bool region_do_rescue_this(WRegion
*tosave_
, WRescueInfo
*info
, int ph_flags
)
370 WClientWin
*cwin
=OBJ_CAST(tosave_
, WClientWin
);
371 WRegion
*tosave
=NULL
;
374 if(cwin
->flags
&CLIENTWIN_UNMAP_RQ
)
376 tosave
=(WRegion
*)cwin
;
377 }else if(info
->flags
®ION_RESCUE_NODEEP
){
380 /* Try to rescue whole groups. */
381 /*tosave=(WRegion*)OBJ_CAST(tosave_, WGroupCW);*/
385 return region_rescue_clientwins(tosave_
, info
);
387 int phf
=(info
->flags
®ION_RESCUE_PHFLAGS_OK
? ph_flags
: 0);
388 WPHolder
*ph
=rescueinfo_pholder(info
);
392 : pholder_attach(info
->ph
, phf
, tosave
));
397 bool region_rescue_some_clientwins(WRegion
*reg
, WRescueInfo
*info
,
398 WRegionIterator
*iter
, void *st
)
406 reg
->flags
|=REGION_CWINS_BEING_RESCUED
;
409 WRegion
*tosave
=iter(st
);
414 if(!region_do_rescue_this(tosave
, info
, 0)){
421 reg
->flags
&=~REGION_CWINS_BEING_RESCUED
;
423 return (fails
==0 && !info
->failed_get
);
427 bool region_rescue_clientwins(WRegion
*reg
, WRescueInfo
*info
)
430 CALL_DYN_RET(ret
, bool, region_rescue_clientwins
, reg
, (reg
, info
));
435 bool region_rescue(WRegion
*reg
, WPHolder
*ph
, int flags
)
444 info
.failed_get
=FALSE
;
446 ret
=region_rescue_clientwins(reg
, &info
);
449 destroy_obj((Obj
*)info
.ph
);
455 bool region_rescue_needed(WRegion
*reg
)
463 info
.failed_get
=FALSE
;
465 return !region_rescue_clientwins(reg
, &info
);
475 ExtlTab
manageparams_to_table(const WManageParams
*mp
)
477 ExtlTab t
=extl_create_table();
478 extl_table_sets_b(t
, "switchto", mp
->switchto
);
479 extl_table_sets_b(t
, "jumpto", mp
->jumpto
);
480 extl_table_sets_b(t
, "userpos", mp
->userpos
);
481 extl_table_sets_b(t
, "dockapp", mp
->dockapp
);
482 extl_table_sets_b(t
, "maprq", mp
->maprq
);
483 extl_table_sets_i(t
, "gravity", mp
->gravity
);
484 extl_table_sets_rectangle(t
, "geom", &(mp
->geom
));
485 extl_table_sets_o(t
, "tfor", (Obj
*)(mp
->tfor
));