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;
}