]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/frame.c
[svn-upgrade] Integrating new upstream version, ion3 (20071130)
[ion3.git] / ioncore / frame.c
index d733c3f46252d475be9d40f990281d86fc43c3dd..f85a29624e04ffcb2ecd2fa7239a000b89e3ca2d 100644 (file)
@@ -3,10 +3,7 @@
  *
  * Copyright (c) Tuomo Valkonen 1999-2007. 
  *
- * 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>
@@ -53,11 +50,32 @@ static void frame_add_mode_bindmaps(WFrame *frame);
 
 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 */
@@ -84,6 +102,9 @@ bool frame_init(WFrame *frame, WWindow *parent, const WFitParams *fp,
     frame->mode=mode;
     frame->tab_min_w=0;
     frame->bar_max_width_q=1.0;
+    frame->quasiact_source=NULL;
+    
+    gr_stylespec_init(&frame->baseattr);
     
     if(!mplex_init((WMPlex*)frame, parent, fp))
         return FALSE;
@@ -117,6 +138,7 @@ void frame_deinit(WFrame *frame)
 {
     frame_free_titles(frame);
     frame_release_brushes(frame);
+    gr_stylespec_unalloc(&frame->baseattr);
     mplex_deinit((WMPlex*)frame);
 }
 
@@ -129,14 +151,15 @@ void frame_deinit(WFrame *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{
         /* mode==FRAME_MODE_TILED || mode==FRAME_MODE_TILED_ALT || mode==FRAME_MODE_UNKNOWN */
        region_add_bindmap((WRegion*)frame, ioncore_mplex_toplevel_bindmap);
@@ -168,7 +191,7 @@ void frame_set_mode(WFrame *frame, WFrameMode mode)
     frame_initialise_gr(frame);
     
     mplex_fit_managed(&frame->mplex);
-    frame_recalc_bar(frame);
+    frame_recalc_bar(frame, TRUE);
     frame_set_background(frame, TRUE);
 }
 
@@ -179,12 +202,15 @@ WFrameMode frame_mode(WFrame *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
 };
 
@@ -201,7 +227,9 @@ const char *frame_mode_extl(WFrame *frame)
 
 
 /*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)
@@ -384,7 +412,7 @@ static bool frame_initialise_titles(WFrame *frame)
         }
     }
     
-    frame_recalc_bar(frame);
+    frame_recalc_bar(frame, FALSE);
 
     return TRUE;
 }
@@ -451,36 +479,36 @@ void frame_size_hints(WFrame *frame, WSizeHints *hints_ret)
     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;
@@ -510,51 +538,56 @@ void frame_size_hints(WFrame *frame, WSizeHints *hints_ret)
 /*{{{ 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)
+static void frame_quasiactivation(WFrame *frame, Obj *src, bool act)
 {
-    bool was, is;
-    
-    was=(frame->quasiactive_count>0);
+    if(frame->quasiact_source==src || act){
+        bool was, is;
+        
+        was=(frame->quasiact_source!=NULL);
     
-    frame->quasiactive_count=maxof(0, frame->quasiactive_count 
-                                       + (act ? 1 : -1));
-                                       
-    is=(frame->quasiactive_count>0);
+        frame->quasiact_source=(act ? src : NULL);
     
-    if(was!=is && !REGION_IS_ACTIVE(frame))
-        window_draw((WWindow*)frame, FALSE);
+        is=(frame->quasiact_source!=NULL);
+        
+        if(was!=is){
+            frame_quasiactivity_change(frame);
+            if(!REGION_IS_ACTIVE(frame))
+                window_draw((WWindow*)frame, FALSE);
+        }
+    }
 }
 
 
 static bool actinact(WRegion *reg, bool act)
 {
     WPHolder *returnph=region_get_return(reg);
-    WFrame *frame;
+    WFrame *frame=NULL;
+    Obj *src=NULL;
+    WRegion *tgt;
     
     if(returnph==NULL || pholder_stale(returnph))
         return FALSE;
     
-    frame=OBJ_CAST(pholder_target(returnph), WFrame);
+    tgt=pholder_target(returnph);
+
+    frame=OBJ_CAST(tgt, WFrame);
     
     if(frame!=NULL){
-        /* Ok, reg has return placeholder set to a frame: 
-         * do quasiactivation/inactivation 
+        src=(Obj*)returnph;
+    }else{
+        /* Show quasiactivation for stuff detached from
+         * groups contained in the frame as well.
          */
-        frame_quasiactivation(frame, reg, act);
+        WGroup *grp=OBJ_CAST(tgt, WGroup);
+        if(grp!=NULL){
+            frame=REGION_MANAGER_CHK(grp, WFrame);
+            src=(Obj*)grp;
+        }
     }
     
+    if(frame!=NULL)
+        frame_quasiactivation(frame, src, act);
+    
     return TRUE;
 }
 
@@ -670,9 +703,10 @@ static WFramedPHolder *frame_make_recreate_pholder(WFrame *frame)
     
     ph=region_make_return_pholder((WRegion*)frame);
     
-    if(ph==NULL)
+    if(ph==NULL){
         return NULL;
-        
+    }
+    
     fparam.mode=frame->mode;
     
     fph=create_framedpholder(ph, &fparam);
@@ -723,6 +757,13 @@ static void frame_modify_pholders(WFrame *frame)
 }
 
 
+bool frame_rescue_clientwins(WFrame *frame, WRescueInfo *info)
+{
+    frame_modify_pholders(frame);
+    return mplex_rescue_clientwins(&frame->mplex, info);
+}
+
+    
 /*}}}*/
 
 
@@ -773,7 +814,8 @@ bool frame_set_shaded(WFrame *frame, int sp)
 
 /*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)
@@ -794,47 +836,67 @@ bool frame_is_shaded(WFrame *frame)
 }
 
 
-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;
+    }
 }
 
 
 void frame_managed_notify(WFrame *frame, WRegion *sub, WRegionNotify how)
 {
-    frame_update_attrs(frame);
-    frame_recalc_bar(frame);
-    frame_draw_bar(frame, FALSE);
+    if(how==ioncore_g.notifies.activated ||
+       how==ioncore_g.notifies.inactivated ||
+       how==ioncore_g.notifies.name ||
+       how==ioncore_g.notifies.activity ||
+       how==ioncore_g.notifies.sub_activity ||
+       how==ioncore_g.notifies.tag){
+       
+        frame_update_attrs(frame);
+        frame_recalc_bar(frame, FALSE);
+        frame_draw_bar(frame, FALSE);
+    }
 }
 
 
@@ -844,7 +906,7 @@ static void frame_size_changed_default(WFrame *frame,
     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))){
@@ -858,6 +920,14 @@ static void frame_managed_changed(WFrame *frame, int mode, bool sw,
 {
     bool need_draw=TRUE;
     
+    if(mode==MPLEX_CHANGE_REMOVE && (Obj*)reg==frame->quasiact_source){
+        /* Reset indirect quasiactivation through group that
+         * is being removed.
+         */
+        frame->quasiact_source=NULL;
+        frame_quasiactivity_change(frame);
+    }
+    
     if(mode!=MPLEX_CHANGE_SWITCHONLY)
         frame_initialise_titles(frame);
     else
@@ -875,33 +945,49 @@ static void frame_managed_changed(WFrame *frame, int mode, bool sw,
 }
 
 
-#define EMPTY_AND_SHOULD_BE_DESTROYED(FRAME) \
-    (DEST_EMPTY(frame) && FRAME_MCOUNT(FRAME)==0 && \
-     !OBJ_IS_BEING_DESTROYED(frame))
-
-
-static void frame_destroy_empty(WFrame *frame)
+WRegion *frame_managed_disposeroot(WFrame *frame, WRegion *reg)
 {
-    if(EMPTY_AND_SHOULD_BE_DESTROYED(frame)){
-        frame_modify_pholders(frame);
-        destroy_obj((Obj*)frame);
+    if(DEST_EMPTY(frame) &&
+       frame->mplex.mgd!=NULL && 
+       frame->mplex.mgd->reg==reg && 
+       frame->mplex.mgd->mgr_next==NULL){
+        WRegion *tmp=region_disposeroot((WRegion*)frame);
+        return (tmp!=NULL ? tmp : reg);
     }
+    
+    return reg;
 }
 
 
-void frame_managed_remove(WFrame *frame, WRegion *reg)
+int frame_default_index(WFrame *frame)
 {
-    mplex_managed_remove((WMPlex*)frame, reg);
-    if(EMPTY_AND_SHOULD_BE_DESTROYED(frame)){
-        mainloop_defer_action((Obj*)frame, 
-                              (WDeferredAction*)frame_destroy_empty);
-    }
+    return ioncore_g.frame_default_index;
 }
 
 
-int frame_default_index(WFrame *frame)
+/*}}}*/
+
+
+/*{{{ prepare_manage_transient */
+
+
+WPHolder *frame_prepare_manage_transient(WFrame *frame,
+                                         const WClientWin *transient,
+                                         const WManageParams *param,
+                                         int unused)
 {
-    return ioncore_g.frame_default_index;
+    /* 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;
+    }
 }
 
 
@@ -960,25 +1046,18 @@ WRegion *frame_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
     int mode=FRAME_MODE_UNKNOWN;
     WFrame *frame;
     
-    if(!extl_table_gets_i(tab, "mode", &mode)){
-        #warning "TODO: Remove backwards compatibility hack"
-        char *style=NULL;
-        if(extl_table_gets_s(tab, "frame_style", &style)){
-            if(strcmp(style, "frame-tiled")==0)
-                mode=FRAME_MODE_TILED;
-            else if(strcmp(style, "frame-floating")==0)
-                mode=FRAME_MODE_FLOATING;
-            else if(strcmp(style, "frame-transientcontainer")==0)
-                mode=FRAME_MODE_TRANSIENT;
-            free(style);
-        }
-    }
+    extl_table_gets_i(tab, "mode", &mode);
     
     frame=create_frame(par, fp, mode);
     
     if(frame!=NULL)
         frame_do_load(frame, tab);
     
+    if(DEST_EMPTY(frame) && frame->mplex.mgd==NULL){
+        destroy_obj((Obj*)frame);
+        return NULL;
+    }
+    
     return (WRegion*)frame;
 }
 
@@ -1015,14 +1094,21 @@ static DynFunTab frame_dynfuntab[]={
 
     {(DynFun*)region_fitrep,
      (DynFun*)frame_fitrep},
+     
+    {(DynFun*)region_managed_disposeroot,
+     (DynFun*)frame_managed_disposeroot},
 
     {region_managed_rqgeom_absolute, 
      frame_managed_rqgeom_absolute},
 
-    {region_managed_remove, frame_managed_remove},
-    
     {(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
 };