/*
* ion/ioncore/frame.c
*
- * Copyright (c) Tuomo Valkonen 1999-2007.
+ * Copyright (c) Tuomo Valkonen 1999-2008.
*
- * 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 <string.h>
WHook *frame_managed_changed_hook=NULL;
-#define IS_FLOATING_MODE(FRAME) \
- ((FRAME)->mode==FRAME_MODE_FLOATING || (FRAME)->mode==FRAME_MODE_TRANSIENT)
-#define FORWARD_CWIN_RQGEOM(FRAME) IS_FLOATING_MODE(FRAME)
-#define USE_MINMAX(FRAME) IS_FLOATING_MODE(FRAME)
-#define DEST_EMPTY(FRAME) IS_FLOATING_MODE(FRAME)
+#define FORWARD_CWIN_RQGEOM(FRAME) framemode_is_floating(frame_mode(FRAME))
+#define USE_MINMAX(FRAME) framemode_is_floating(frame_mode(FRAME))
+#define DEST_EMPTY(FRAME) framemode_is_floating(frame_mode(FRAME))
+
+
+WFrameMode framemode_unalt(WFrameMode mode)
+{
+ if(mode==FRAME_MODE_UNKNOWN_ALT)
+ return FRAME_MODE_UNKNOWN;
+ else if(mode==FRAME_MODE_TILED_ALT)
+ return FRAME_MODE_TILED;
+ else if(mode==FRAME_MODE_FLOATING_ALT)
+ return FRAME_MODE_FLOATING;
+ else if(mode==FRAME_MODE_TRANSIENT_ALT)
+ return FRAME_MODE_TRANSIENT;
+ else
+ return mode;
+}
+
+
+static WFrameMode framemode_is_floating(WFrameMode mode)
+{
+ WFrameMode modea=framemode_unalt(mode);
+
+ return (modea==FRAME_MODE_FLOATING || modea==FRAME_MODE_TRANSIENT);
+}
/*{{{ Destroy/create frame */
frame->tab_min_w=0;
frame->bar_max_width_q=1.0;
+ gr_stylespec_init(&frame->baseattr);
+
if(!mplex_init((WMPlex*)frame, parent, fp))
return FALSE;
{
frame_free_titles(frame);
frame_release_brushes(frame);
+ gr_stylespec_unalloc(&frame->baseattr);
mplex_deinit((WMPlex*)frame);
}
static void frame_add_mode_bindmaps(WFrame *frame)
{
- WFrameMode mode=frame->mode;
+ WFrameMode modea=framemode_unalt(frame->mode);
- if(mode==FRAME_MODE_FLOATING){
+ if(modea==FRAME_MODE_FLOATING){
region_add_bindmap((WRegion*)frame, ioncore_mplex_toplevel_bindmap);
region_add_bindmap((WRegion*)frame, ioncore_frame_toplevel_bindmap);
region_add_bindmap((WRegion*)frame, ioncore_frame_floating_bindmap);
- }else if(mode==FRAME_MODE_TRANSIENT){
+ }else if(modea==FRAME_MODE_TRANSIENT){
region_add_bindmap((WRegion*)frame, ioncore_frame_transient_bindmap);
region_add_bindmap((WRegion*)frame, ioncore_frame_floating_bindmap);
}else{
region_remove_bindmap((WRegion*)frame, ioncore_frame_transient_bindmap);
frame->mode=mode;
-
- frame_add_mode_bindmaps(frame);
- frame_initialise_gr(frame);
+ frame_add_mode_bindmaps(frame);
- mplex_fit_managed(&frame->mplex);
- frame_recalc_bar(frame);
- frame_set_background(frame, TRUE);
+ frame_updategr(frame);
}
}
-StringIntMap frame_modes[]={
+static StringIntMap frame_modes[]={
{"unknown", FRAME_MODE_UNKNOWN},
+ {"unknown-alt", FRAME_MODE_UNKNOWN_ALT},
{"tiled", FRAME_MODE_TILED},
{"tiled-alt", FRAME_MODE_TILED_ALT},
{"floating", FRAME_MODE_FLOATING},
+ {"floating-alt", FRAME_MODE_FLOATING_ALT},
{"transient", FRAME_MODE_TRANSIENT},
+ {"transient-alt", FRAME_MODE_TRANSIENT_ALT},
END_STRINGINTMAP
};
/*EXTL_DOC
- * Set frame mode.
+ * Set frame mode (one of
+ * \codestr{unknown}, \codestr{tiled}, \codestr{floating}, \codestr{transient},
+ * or any of these suffixed with \codestr{-alt}).
*/
EXTL_EXPORT_AS(WFrame, set_mode)
bool frame_set_mode_extl(WFrame *frame, const char *modestr)
}
}
- frame_recalc_bar(frame);
+ frame_recalc_bar(frame, FALSE);
return TRUE;
}
old_geom=REGION_GEOM(frame);
- window_do_fitrep(&(frame->mplex.win), par, &(fp->g));
+ if(!window_fitrep(&(frame->mplex.win), par, fp))
+ return FALSE;
mplex_managed_geom((WMPlex*)frame, &mg);
woff=maxof(REGION_GEOM(frame).w-subgeom.w, 0);
hoff=maxof(REGION_GEOM(frame).h-subgeom.h, 0);
- if(FRAME_CURRENT(frame)!=NULL){
+ if(FRAME_CURRENT(frame)!=NULL)
region_size_hints(FRAME_CURRENT(frame), hints_ret);
- if(!USE_MINMAX(frame)){
- hints_ret->max_set=0;
- hints_ret->min_set=0;
- /*hints_ret->base_set=0;*/
- hints_ret->aspect_set=0;
- hints_ret->no_constrain=FALSE;
- /*hints_ret->no_constrain=TRUE;*/
- }
- }else{
+ else
sizehints_clear(hints_ret);
- }
FRAME_MX_FOR_ALL(sub, frame, tmp){
sizehints_adjust_for(hints_ret, sub);
}
- if(!hints_ret->base_set){
- hints_ret->base_width=0;
- hints_ret->base_height=0;
- hints_ret->base_set=TRUE;
+ if(!USE_MINMAX(frame)){
+ hints_ret->max_set=0;
+ hints_ret->min_set=0;
+ /*hints_ret->base_set=0;*/
+ hints_ret->aspect_set=0;
+ hints_ret->no_constrain=FALSE;
+ /*hints_ret->no_constrain=TRUE;*/
}
-
+
if(!hints_ret->min_set){
hints_ret->min_width=0;
hints_ret->min_height=0;
hints_ret->min_set=TRUE;
}
+ if(!hints_ret->base_set){
+ hints_ret->base_width=0;
+ hints_ret->base_height=0;
+ hints_ret->base_set=TRUE;
+ }
+
hints_ret->base_width+=woff;
hints_ret->base_height+=hoff;
hints_ret->max_width+=woff;
hints_ret->min_width+=woff;
hints_ret->min_height+=hoff;
- if(frame->barmode==FRAME_BAR_SHAPED){
+ /* shaded */ {
int f=frame->flags&(FRAME_SHADED|FRAME_SHADED_TOGGLE);
if(f==FRAME_SHADED || f==FRAME_SHADED_TOGGLE){
- hints_ret->min_height=frame->bar_h;
- hints_ret->max_height=frame->bar_h;
- hints_ret->base_height=frame->bar_h;
+ int h=frame_shaded_height(frame);
+ hints_ret->min_height=h;
+ hints_ret->max_height=h;
+ hints_ret->base_height=h;
if(!hints_ret->max_set){
hints_ret->max_width=INT_MAX;
hints_ret->max_set=TRUE;
/*}}}*/
-/*{{{ Focus */
-
-
-void frame_inactivated(WFrame *frame)
-{
- window_draw((WWindow*)frame, FALSE);
-}
-
-
-void frame_activated(WFrame *frame)
-{
- window_draw((WWindow*)frame, FALSE);
-}
-
-
-void frame_quasiactivation(WFrame *frame, WRegion *reg, bool act)
-{
- bool was, is;
-
- was=(frame->quasiactive_count>0);
-
- frame->quasiactive_count=maxof(0, frame->quasiactive_count
- + (act ? 1 : -1));
-
- is=(frame->quasiactive_count>0);
-
- if(was!=is && !REGION_IS_ACTIVE(frame))
- window_draw((WWindow*)frame, FALSE);
-}
-
-
-static bool actinact(WRegion *reg, bool act)
-{
- WPHolder *returnph=region_get_return(reg);
- WFrame *frame;
-
- if(returnph==NULL || pholder_stale(returnph))
- return FALSE;
-
- frame=OBJ_CAST(pholder_target(returnph), WFrame);
-
- if(frame!=NULL){
- /* Ok, reg has return placeholder set to a frame:
- * do quasiactivation/inactivation
- */
- frame_quasiactivation(frame, reg, act);
- }
-
- return TRUE;
-}
-
-
-static bool activated(WRegion *reg)
-{
- return actinact(reg, TRUE);
-}
-
-
-static bool inactivated(WRegion *reg)
-{
- return actinact(reg, FALSE);
-}
-
-
-void ioncore_frame_quasiactivation_notify(WRegion *reg,
- WRegionNotify how)
-{
- if(how==ioncore_g.notifies.activated ||
- how==ioncore_g.notifies.pseudoactivated){
- activated(reg);
- }else if(how==ioncore_g.notifies.inactivated ||
- how==ioncore_g.notifies.pseudoinactivated){
- inactivated(reg);
- }else if(how==ioncore_g.notifies.set_return){
- if(REGION_IS_ACTIVE(reg) || REGION_IS_PSEUDOACTIVE(reg))
- activated(reg);
- }else if(how==ioncore_g.notifies.unset_return){
- if(REGION_IS_ACTIVE(reg) || REGION_IS_PSEUDOACTIVE(reg))
- inactivated(reg);
- }
-}
-
-
-/*}}}*/
-
-
/*{{{ Client window rqgeom */
/*{{{ Frame recreate pholder stuff */
-static WFramedPHolder *frame_make_recreate_pholder(WFrame *frame)
+static WFramedPHolder *frame_make_recreate_pholder(WFrame *frame, WPHolder *rph)
{
- WPHolder *ph;
- WFramedPHolder *fph;
WFramedParam fparam=FRAMEDPARAM_INIT;
+ WFramedPHolder *fph=NULL;
- ph=region_make_return_pholder((WRegion*)frame);
-
- if(ph==NULL)
- return NULL;
-
- fparam.mode=frame->mode;
+ if(rph!=NULL){
+ fparam.mode=frame->mode;
- fph=create_framedpholder(ph, &fparam);
+ fph=create_framedpholder(rph, &fparam);
- if(fph==NULL){
- destroy_obj((Obj*)ph);
- return NULL;
+ if(fph==NULL)
+ destroy_obj((Obj*)rph);
}
return fph;
}
-static void mplex_flatten_phs(WMPlex *mplex)
-{
- WLListNode *node;
- WLListIterTmp tmp;
-
- FOR_ALL_NODES_ON_LLIST(node, mplex->mx_list, tmp){
- WMPlexPHolder *last=(mplex->mx_phs==NULL ? NULL : mplex->mx_phs->prev);
- mplex_move_phs(mplex, node, last, NULL);
- }
-}
-
-
-static void frame_modify_pholders(WFrame *frame)
+static void mplex_migrate_phs_to_fph(WMPlex *mplex, WFramedPHolder *fph)
{
- WFramedPHolder *fph;
WMPlexPHolder *phs, *ph;
- mplex_flatten_phs(&frame->mplex);
+ phs=mplex->misc_phs;
+ mplex->misc_phs=NULL;
- if(frame->mplex.mx_phs==NULL)
- return;
+ phs->recreate_pholder=fph;
- fph=frame_make_recreate_pholder(frame);
+ for(ph=phs; ph!=NULL; ph=ph->next)
+ ph->mplex=NULL;
+}
+
+
+
+bool frame_rescue_clientwins(WFrame *frame, WRescueInfo *info)
+{
+ bool ret;
- if(fph==NULL)
- return;
+ ret=mplex_rescue_clientwins(&frame->mplex, info);
- phs=frame->mplex.mx_phs;
- frame->mplex.mx_phs=NULL;
+ /* Now, do placeholders.
+ * We can't currently be arsed to keep them ordered with regions...
+ * First we check if we can simply recreate this frame, which takes
+ * care of e.g. floating frames being destroyed when entering full
+ * screen mode. If not, we check if the target would be a WMPlex, and
+ * migrate there. This takes care of frames destroyed in tilings.
+ */
+ mplex_flatten_phs(&frame->mplex);
- phs->recreate_pholder=fph;
+ if(frame->mplex.misc_phs!=NULL){
+ WPHolder *ret_ph=region_make_return_pholder((WRegion*)frame);
+ WFramedPHolder *fph=frame_make_recreate_pholder(frame, ret_ph);
+
+ if(fph!=NULL){
+ mplex_migrate_phs_to_fph(&frame->mplex, fph);
+ }else{
+ WPHolder *rescueph=rescueinfo_pholder(info);
+ if(rescueph!=NULL){
+ WRegion *target=pholder_target(rescueph);
+ WMPlex *other_mplex=OBJ_CAST(target, WMPlex);
+
+ if(other_mplex!=NULL){
+ assert(other_mplex!=&frame->mplex);
+ mplex_migrate_phs(&frame->mplex, other_mplex);
+ }
+ }
+ }
+ }
- for(ph=phs; ph!=NULL; ph=ph->next)
- watch_reset(&ph->mplex_watch);
+ return ret;
}
return FALSE;
rq.geom.h=frame->saved_h;
}else{
- if(frame->barmode==FRAME_BAR_NONE){
+ if(frame->barmode==FRAME_BAR_NONE)
return FALSE;
- }else if(frame->barmode==FRAME_BAR_SHAPED){
- rq.geom.h=frame->bar_h;
- }else{
- WRectangle tmp;
-
- frame_border_inner_geom(frame, &tmp);
-
- rq.geom.h=rq.geom.h-tmp.h;
- }
+ rq.geom.h=frame_shaded_height(frame);
}
frame->flags|=FRAME_SHADED_TOGGLE;
/*EXTL_DOC
* Set shading state according to the parameter \var{how}
- * (set/unset/toggle). Resulting state is returned, which may not be
+ * (\codestr{set}, \codestr{unset}, or \codestr{toggle}).
+ * Resulting state is returned, which may not be
* what was requested.
*/
EXTL_EXPORT_AS(WFrame, set_shaded)
}
-bool frame_set_numbers(WFrame *frame, int sp)
+/* EXTL_DOC
+ * Is the attribute \var{attr} set?
+ */
+bool frame_is_grattr(WFrame *frame, const char *attr)
{
- bool set=frame->flags&FRAME_SHOW_NUMBERS;
- bool nset=libtu_do_setparam(sp, set);
-
- if(XOR(nset, set)){
- frame->flags^=FRAME_SHOW_NUMBERS;
- frame_recalc_bar(frame);
- frame_draw_bar(frame, TRUE);
- }
-
- return frame->flags&FRAME_SHOW_NUMBERS;
+ GrAttr a=stringstore_alloc(attr);
+ bool set=gr_stylespec_isset(&frame->baseattr, a);
+ stringstore_free(a);
+ return set;
}
-/*EXTL_DOC
- * Control whether tabs show numbers (set/unset/toggle).
- * Resulting state is returned, which may not be what was
- * requested.
- */
-EXTL_EXPORT_AS(WFrame, set_numbers)
-bool frame_set_numbers_extl(WFrame *frame, const char *how)
+bool frame_set_grattr(WFrame *frame, GrAttr a, int sp)
{
- return frame_set_numbers(frame, libtu_string_to_setparam(how));
+ bool set=gr_stylespec_isset(&frame->baseattr, a);
+ bool nset=libtu_do_setparam(sp, set);
+
+ if(XOR(set, nset)){
+ if(nset)
+ gr_stylespec_set(&frame->baseattr, a);
+ else
+ gr_stylespec_unset(&frame->baseattr, a);
+ window_draw((WWindow*)frame, TRUE);
+ }
+
+ return nset;
}
/*EXTL_DOC
- * Does \var{frame} show numbers for tabs?
+ * Set extra drawing engine attributes for the frame.
+ * The parameter \var{attr} is the attribute, and \var{how} is
+ * one of \codestr{set}, \codestr{unset}, or \codestr{toggle}.
*/
-bool frame_is_numbers(WFrame *frame)
+EXTL_EXPORT_AS(WFrame, set_grattr)
+bool frame_set_grattr_extl(WFrame *frame, const char *attr, const char *how)
{
- return frame->flags&FRAME_SHOW_NUMBERS;
+ if(attr!=NULL){
+ GrAttr a=stringstore_alloc(attr);
+ bool ret=frame_set_grattr(frame, a, libtu_string_to_setparam(how));
+ stringstore_free(a);
+ return ret;
+ }else{
+ return FALSE;
+ }
}
how==ioncore_g.notifies.tag){
frame_update_attrs(frame);
- frame_recalc_bar(frame);
+ frame_recalc_bar(frame, FALSE);
frame_draw_bar(frame, FALSE);
}
}
int bar_w=frame->bar_w;
if(wchg)
- frame_recalc_bar(frame);
+ frame_recalc_bar(frame, TRUE);
if(frame->barmode==FRAME_BAR_SHAPED &&
((!wchg && hchg) || (wchg && bar_w==frame->bar_w))){
if(DEST_EMPTY(frame) &&
frame->mplex.mgd!=NULL &&
frame->mplex.mgd->reg==reg &&
- frame->mplex.mgd->next==NULL){
+ frame->mplex.mgd->mgr_next==NULL){
WRegion *tmp=region_disposeroot((WRegion*)frame);
return (tmp!=NULL ? tmp : reg);
}
/*}}}*/
+/*{{{ prepare_manage_transient */
+
+
+WPHolder *frame_prepare_manage_transient(WFrame *frame,
+ const WClientWin *transient,
+ const WManageParams *param,
+ int unused)
+{
+ /* Transient manager searches should not cross tiled frames
+ * unless explicitly floated.
+ */
+ if(framemode_is_floating(frame_mode(frame)) ||
+ extl_table_is_bool_set(transient->proptab, "float")){
+ return region_prepare_manage_transient_default((WRegion*)frame,
+ transient,
+ param,
+ unused);
+ }else{
+ return NULL;
+ }
+}
+
+
+/*}}}*/
+
+
/*{{{ Save/load */
int mode=FRAME_MODE_UNKNOWN;
WFrame *frame;
- extl_table_gets_i(tab, "mode", &mode);
+ if(!extl_table_gets_i(tab, "mode", &mode)){
+ char *tmp;
+ if(extl_table_gets_s(tab, "mode", &tmp)){
+ mode=stringintmap_value(frame_modes, tmp, mode);
+ free(tmp);
+ }
+ }
frame=create_frame(par, fp, mode);
frame_do_load(frame, tab);
if(DEST_EMPTY(frame) && frame->mplex.mgd==NULL){
+ if(frame->mplex.misc_phs!=NULL){
+ /* Session management hack */
+ WFramedPHolder *fph;
+ fph=frame_make_recreate_pholder(frame, ioncore_get_load_pholder());
+ if(fph!=NULL)
+ mplex_migrate_phs_to_fph(&frame->mplex, fph);
+ }
+
destroy_obj((Obj*)frame);
return NULL;
}
{(DynFun*)mplex_default_index,
(DynFun*)frame_default_index},
+
+ {(DynFun*)region_prepare_manage_transient,
+ (DynFun*)frame_prepare_manage_transient},
+
+ {(DynFun*)region_rescue_clientwins,
+ (DynFun*)frame_rescue_clientwins},
END_DYNFUNTAB
};