Public Instance methods
grab(chain, value) -> nil
grab(chain, &blk) -> nil
Create a new grab either to start a program, with a predefined action or with a code block or start a program
grab "W-Return", "urxvt" grab "W-S-1", :ViewJump1 grab "A-F2" do |c| puts c.name end grab "S-F3" do puts Subtlext::VERSION end
[show source]
static VALUE RubyConfigGrab(int argc, VALUE *argv, VALUE self) { VALUE chain = Qnil, value = Qnil; rb_scan_args(argc, argv, "11", &chain, &value); if(rb_block_given_p()) value = rb_block_proc(); ///< Get proc RubyEvalGrab(chain, value); return Qnil; }
gravity(name, value, tile) -> nil
Create a new gravity and optionally enable tiling, either horizonally (:horz) or vertically. (:vert) inside of the grid
subforge.org/projects/subtle/wiki/Gravity
gravity :top_left, [0, 0, 50, 50] gravity :top_left, [0, 0, 50, 50], :vert
[show source]
static VALUE RubyConfigGravity(int argc, VALUE *argv, VALUE self) { VALUE name = Qnil, value = Qnil, tile = Qnil; rb_scan_args(argc, argv, "21", &name, &value, &tile); /* Check value type */ if(T_SYMBOL == rb_type(name) && T_ARRAY == rb_type(value)) { XRectangle geometry = { 0 }; RubyArrayToGeometry(value, &geometry); /* Skip on checking only */ if(!(subtle->flags & SUB_SUBTLE_CHECK)) { SubGravity *g = NULL; /* Finally create new gravity */ if((g = subGravityNew(SYM2CHAR(name), &geometry))) { /* Tile just clients with this gravity */ if(T_SYMBOL == rb_type(tile)) { if(CHAR2SYM("horz") == tile) g->flags |= SUB_GRAVITY_HORZ; else if(CHAR2SYM("vert") == tile) g->flags |= SUB_GRAVITY_VERT; } subArrayPush(subtle->gravities, (void *)g); } } } else rb_raise(rb_eArgError, "Unknown value type for gravity"); return Qnil; }
on(event, &block) -> nil
Create a new event handler for a hook
on :client_focus do |s| puts s.name end
[show source]
static VALUE RubyConfigOn(int argc, VALUE *argv, VALUE self) { VALUE event = Qnil, value = Qnil; rb_scan_args(argc, argv, "11", &event, &value); /* Check value type */ if(T_SYMBOL == rb_type(event)) { if(subtle->flags & SUB_SUBTLE_CHECK) return Qnil; ///< Skip on check if(rb_block_given_p()) value = rb_block_proc(); ///< Get proc RubyEvalHook(event, value); } else rb_raise(rb_eArgError, "Unknown value type for on"); return Qnil; }
screen(screenid, blk) -> nil
Split a physical screen in virtual ones
subforge.org/projects/subtle/wiki/Config/#Screens
screen 1 do virtual [ 0, 0, 50, 100 ] virtual [ 50, 0, 50, 100 ] end
[show source]
static VALUE RubyConfigScreen(VALUE self, VALUE screenid) { rb_need_block(); /* Check value type */ if(FIXNUM_P(screenid)) { int idx = FIX2INT(screenid); VALUE klass = Qnil, options = Qnil, params = Qnil, value = Qnil; if(subtle->flags & SUB_SUBTLE_CHECK) return Qnil; ///< Skip on check /* Sanity check */ if(idx - 1 > subtle->screens->ndata) { rb_raise(rb_eArgError, "Invalid screeen id `%d'", idx); return Qnil; } /* Collect options */ klass = rb_const_get(mod, rb_intern("Options")); options = rb_funcall(klass, rb_intern("new"), 1, self); rb_obj_instance_eval(0, 0, options); params = rb_iv_get(options, "@params"); /* Eval virtuals */ if(T_ARRAY == rb_type(value = rb_hash_lookup(params, CHAR2SYM("virtual")))) { int i, count = 0, vgeom[4] = { 0 }; VALUE entry = Qnil; SubScreen *s = SCREEN(subArrayGet(subtle->screens, idx - 1)); if(s && !(s->flags & SUB_SCREEN_VIRTUAL)) ///< Do this just once { for(i = 0; Qnil != (entry = rb_ary_entry(value, i)); i++) { if(FIXNUM_P(entry)) { vgeom[count++] = FIX2INT(entry); if(4 == count) { SubScreen *vscreen = NULL; vscreen = subScreenNew( s->geom.x + (s->geom.width * vgeom[0] / 100), s->geom.y + (s->geom.height * vgeom[1] / 100), s->geom.width * vgeom[2] / 100, s->geom.height * vgeom[3] / 100); vscreen->flags |= SUB_SCREEN_VIRTUAL; subArrayInsert(subtle->screens, (idx++ - 1), (void *)vscreen); count = 0; } } } subArrayRemove(subtle->screens, (void *)s); subScreenResize(); } } } else rb_raise(rb_eArgError, "Unexpected value type for screen `%s'", rb_obj_classname(screenid)); return Qnil; }
set(option, value) -> nil
[show source]
static VALUE RubyConfigSet(VALUE self, VALUE option, VALUE value) { /* Check value type */ if(T_SYMBOL == rb_type(option)) { switch(rb_type(value)) { case T_FIXNUM: /* {{{ */ if(CHAR2SYM("step") == option || CHAR2SYM("increase_step") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK)) subtle->step = FIX2INT(value); } else if(CHAR2SYM("snap") == option || CHAR2SYM("border_snap") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK)) subtle->snap = FIX2INT(value); } else if(CHAR2SYM("gravity") == option || CHAR2SYM("default_gravity") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK)) subtle->gravity = value; ///< Store for later } else subSubtleLogWarn("Unknown option `:%s'\n", SYM2CHAR(option)); break; /* }}} */ case T_SYMBOL: /* {{{ */ if(CHAR2SYM("gravity") == option || CHAR2SYM("default_gravity") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK)) subtle->gravity = value; ///< Store for later } else subSubtleLogWarn("Unknown option `:%s'\n", SYM2CHAR(option)); break; /* }}} */ case T_TRUE: case T_FALSE: /* {{{ */ if(CHAR2SYM("urgent") == option || CHAR2SYM("urgent_dialogs") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK) && Qtrue == value) subtle->flags |= SUB_SUBTLE_URGENT; } else if(CHAR2SYM("resize") == option || CHAR2SYM("honor_size_hints") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK) && Qtrue == value) subtle->flags |= SUB_SUBTLE_RESIZE; } else if(CHAR2SYM("tiling") == option || CHAR2SYM("gravity_tiling") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK) && Qtrue == value) subtle->flags |= SUB_SUBTLE_TILING; } else if(CHAR2SYM("click_to_focus") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK) && Qtrue == value) subtle->flags |= SUB_SUBTLE_FOCUS_CLICK; } else if(CHAR2SYM("skip_pointer_warp") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK) && Qtrue == value) subtle->flags |= SUB_SUBTLE_SKIP_WARP; } else if(CHAR2SYM("skip_urgent_warp") == option) { if(!(subtle->flags & SUB_SUBTLE_CHECK) && Qtrue == value) subtle->flags |= SUB_SUBTLE_SKIP_URGENT_WARP; } else subSubtleLogWarn("Unknown option `:%s'\n", SYM2CHAR(option)); break; /* }}} */ case T_STRING: /* {{{ */ if(CHAR2SYM("wmname") == option) { /* Set support window to root (broken Java) * and update WM_NAME */ if(!(subtle->flags & SUB_SUBTLE_CHECK)) { Window root = ROOT; subEwmhSetWindows(ROOT, SUB_EWMH_NET_SUPPORTING_WM_CHECK, &root, 1); subEwmhSetString(root, SUB_EWMH_NET_WM_NAME, RSTRING_PTR(value)); } } else subSubtleLogWarn("Unknown option `:%s'\n", SYM2CHAR(option)); break; /* }}} */ default: rb_raise(rb_eArgError, "Unexpected value type for option `%s'", SYM2CHAR(option)); } } else rb_raise(rb_eArgError, "Unexpected value type for set"); return Qnil; }
style(name, blk) -> nil
Set propeties of named styles
style :title do foreground "#fecf35" end
[show source]
static VALUE RubyConfigStyle(VALUE self, VALUE name) { rb_need_block(); /* Check value type */ if(T_SYMBOL == rb_type(name)) { SubStyle *style = NULL; VALUE klass = Qnil, options = Qnil, styles = Qnil; /* Select style struct */ if(CHAR2SYM("all") == name) style = &subtle->styles.all; else if(CHAR2SYM("views") == name) style = &subtle->styles.views; else if(CHAR2SYM("title") == name) style = &subtle->styles.title; else if(CHAR2SYM("sublets") == name) style = &subtle->styles.sublets; else if(CHAR2SYM("separator") == name) style = &subtle->styles.separator; else if(CHAR2SYM("clients") == name) style = &subtle->styles.clients; else if(CHAR2SYM("panel_top") == name) style = &subtle->styles.panel_top; else if(CHAR2SYM("panel_bottom") == name) style = &subtle->styles.panel_bot; else if(CHAR2SYM("tray") == name) style = &subtle->styles.tray; else { subSubtleLogWarn("Unexpected style name `:%s'\n", SYM2CHAR(name)); return Qnil; } if(subtle->flags & SUB_SUBTLE_CHECK) return Qnil; ///< Skip on check /* Collect options */ klass = rb_const_get(mod, rb_intern("Options")); options = rb_funcall(klass, rb_intern("new"), 1, self); rb_obj_instance_eval(0, 0, options); /* Eval style before nested styles */ RubyEvalStyle(name, style, rb_iv_get(options, "@params")); /* Eval styles */ if(T_HASH == rb_type((styles = rb_iv_get(options, "@styles")))) rb_hash_foreach(styles, RubyForeachStyle, (VALUE)style); } else rb_raise(rb_eArgError, "Unexpected value type for style `%s'", rb_obj_classname(name)); return Qnil; }
sublet(name, blk) -> nil
Set properties of sublets
subforge.org/projects/subtle/wiki/Sublets
sublet :clock do interval 20 foreground "#eeeeee" background "#000000" format_string "%H:%M:%S" end
[show source]
static VALUE RubyConfigSublet(VALUE self, VALUE sublet) { VALUE klass = Qnil, options = Qnil; rb_need_block(); /* Check value type */ if(T_SYMBOL == rb_type(sublet)) { /* Collect options */ klass = rb_const_get(mod, rb_intern("Options")); options = rb_funcall(klass, rb_intern("new"), 1, self); rb_obj_instance_eval(0, 0, options); /* Clone to get rid of object instance and store it */ rb_hash_aset(config_sublets, sublet, rb_obj_clone(rb_iv_get(options, "@params"))); } else rb_raise(rb_eArgError, "Unknown value type for sublet"); return Qnil; }
tag(name, regex) -> nil
tag(name, blk) -> nil
Create a new tag either with a regexp or with a block to set additional properties
subforge.org/projects/subtle/wiki/Tagging
tag "terms", "xterm|[u]?rxvt" tag "terms" do match "xterm|[u]?rxvt" gravity :center end
[show source]
static VALUE RubyConfigTag(int argc, VALUE *argv, VALUE self) { int flags = 0, screenid = -1; unsigned long gravityid = 0; XRectangle geom = { 0 }; VALUE name = Qnil, match = Qnil, params = Qnil, value = Qnil, proc = Qnil; rb_scan_args(argc, argv, "11", &name, &match); /* Call proc */ if(rb_block_given_p()) { VALUE klass = Qnil, options = Qnil; /* Collect options */ klass = rb_const_get(mod, rb_intern("Options")); options = rb_funcall(klass, rb_intern("new"), 1, self); rb_obj_instance_eval(0, 0, options); params = rb_iv_get(options, "@params"); /* Check matcher */ if(!NIL_P(value = rb_hash_lookup(params, CHAR2SYM("match")))) match = value; ///< Lazy eval /* Set gravity */ if(T_SYMBOL == rb_type(value = rb_hash_lookup(params, CHAR2SYM("gravity"))) || T_FIXNUM == rb_type(value) || T_ARRAY == rb_type(value)) { flags |= SUB_TAG_GRAVITY; gravityid = value; ///< Lazy eval } /* Set geometry */ if(T_ARRAY == rb_type(value = rb_hash_lookup(params, CHAR2SYM("geometry")))) { flags |= SUB_TAG_GEOMETRY; RubyArrayToGeometry(value, &geom); } /* Set position */ if(T_ARRAY == rb_type(value = rb_hash_lookup(params, CHAR2SYM("position")))) { flags |= SUB_TAG_POSITION; RubyArrayToGeometry(value, &geom); } /* Set window type */ if(T_SYMBOL == rb_type(value = rb_hash_lookup(params, CHAR2SYM("type")))) RubySymbolToFlag(value, &flags); /* Set modes */ if(T_SYMBOL == rb_type(value = rb_hash_lookup(params, CHAR2SYM("set")))) { RubySymbolToFlag(value, &flags); } else if(T_ARRAY == rb_type(value)) { int i; VALUE entry = Qnil; /* Translate modes */ for(i = 0; Qnil != (entry = rb_ary_entry(value, i)); i++) RubySymbolToFlag(entry, &flags); } /* Set stick screen */ if(RTEST(value = rb_hash_lookup(params, CHAR2SYM("stick_to")))) { /* Set screen id if any */ if(FIXNUM_P(value)) { screenid = FIX2INT(value); flags |= (SUB_CLIENT_MODE_STICK|SUB_CLIENT_MODE_STICK_SCREEN); } } /* Set match proc */ if(RTEST(value = rb_hash_lookup(params, CHAR2SYM("on_match")))) { proc = value; flags |= SUB_TAG_PROC; rb_ary_push(shelter, proc); ///< Protect from GC } } /* Check value type */ if(T_STRING == rb_type(name)) { /* Skip on checking only */ if(!(subtle->flags & SUB_SUBTLE_CHECK)) { int duplicate = False; SubTag *t = NULL; /* Finally create and add new tag if no duplicate */ if((t = subTagNew(RSTRING_PTR(name), &duplicate)) && False == duplicate) { int i; VALUE entry = Qnil, rargs[2] = { 0 }; /* Set tag values */ t->flags |= flags; t->gravityid = gravityid; t->screenid = screenid; t->geom = geom; t->proc = proc; /* Add matcher */ rargs[0] = (VALUE)t; switch(rb_type(match)) { case T_HASH: rargs[1] = 0; ///< Reset matcher count rb_hash_foreach(match, RubyForeachMatcher, (VALUE)&rargs); break; case T_ARRAY: for(i = 0; T_HASH == rb_type(entry = rb_ary_entry(match, i)); i++) { rargs[1] = 0; ///< Reset matcher count rb_hash_foreach(entry, RubyForeachMatcher, (VALUE)&rargs); } break; case T_REGEXP: case T_STRING: RubyForeachMatcher(Qnil, match, (VALUE)&rargs); } subArrayPush(subtle->tags, (void *)t); } } } else rb_raise(rb_eArgError, "Unknown value type for tag"); return Qnil; }
view(name, regex) -> nil
Create a new view with a regex to match tags
subforge.org/projects/subtle/wiki/Views
view "foobar", "regex"
[show source]
static VALUE RubyConfigView(int argc, VALUE *argv, VALUE self) { int flags = 0; VALUE name = Qnil, match = Qnil, params = Qnil, value = Qnil, icon = value; rb_scan_args(argc, argv, "11", &name, &match); /* Call proc */ if(rb_block_given_p()) { VALUE klass = Qnil, options = Qnil; /* Collect options */ klass = rb_const_get(mod, rb_intern("Options")); options = rb_funcall(klass, rb_intern("new"), 1, self); rb_obj_instance_eval(0, 0, options); params = rb_iv_get(options, "@params"); /* Check match */ match = rb_hash_lookup(params, CHAR2SYM("match")); ///< Lazy eval /* Set modes */ if(T_SYMBOL == rb_type(value = rb_hash_lookup(params, CHAR2SYM("set")))) { RubySymbolToFlag(value, &flags); } else if(T_ARRAY == rb_type(value)) { int i; VALUE entry = Qnil; /* Translate modes */ for(i = 0; Qnil != (entry = rb_ary_entry(value, i)); i++) RubySymbolToFlag(entry, &flags); } /* Check icon */ icon = RubyValueToIcon(rb_hash_lookup(params, CHAR2SYM("icon"))); } /* Check value type */ if(T_STRING == rb_type(name)) { /* Skip on checking only */ if(!(subtle->flags & SUB_SUBTLE_CHECK)) { SubView *v = NULL; char *re = NULL; /* Convert type */ switch(rb_type(match)) { case T_REGEXP: match = rb_funcall(match, rb_intern("source"), 0, NULL); case T_STRING: re = RSTRING_PTR(match); break; } /* Finally create new view */ if((v = subViewNew(RSTRING_PTR(name), re))) { v->flags |= flags; subArrayPush(subtle->views, (void *)v); /* Add icon */ if(!NIL_P(icon)) { v->flags |= SUB_VIEW_ICON; v->icon = ICON(subSharedMemoryAlloc(1, sizeof(SubIcon))); RubyIconToIcon(icon, v->icon); rb_ary_push(shelter, icon); ///< Protect from GC } else v->flags &= ~SUB_VIEW_ICON_ONLY; } } } else rb_raise(rb_eArgError, "Unknown value type for view"); return Qnil; }