0
Help us understand the problem. What are the problem?
Organization

Mac用ウィンドウマネージャ Slate

Mac用ウィンドウマネージャ Slate

はじめに

Mac用のウィンドウマネージャ(ウィンドウの整列やサイズ調整を行うソフトウェア) Slateを紹介します。

導入

homebrew の導入については割愛します。

$ brew install --cask slate

Slate 実行後 システム環境設定 -> プライバシー で Slate.app にチェックマークを入れる必要があります。

設定例

設定ファイルはホームディレクトリ直下 .slate.js です。
Javascriptで記述されるので Javascriptに慣れた方にとってはとっつきやすいかも知れません。
(ただしES5以前の仕様であることにはご注意下さい)

関数

var util = {
  // アプリ起動・フォーカス
  // http://d.hatena.ne.jp/sugyan/20130301/1362129310
  launch_and_focus: function (target) {
    return function (win) {
      var apps = [];
      S.eachApp(function (app) { apps.push(app.name()); });
      if (! _.find(apps, function (name) { return name === target; })) {
        win.doOperation(
          S.operation('shell', {
            command: "/usr/bin/open -a " + target,
            waithFoeExit: true
          })
        );
      }
      win.doOperation(S.operation('focus', { app: target }));
    };
  },

  // ラッパー
  // http://www.infiniteloop.co.jp/blog/2013/08/osx_slate/
  //
  //   util.key('x')          -> x:alt
  //   util.key('x', 'shift') -> x:alt,shift
  key: function(k, mod) {
    return k + ':alt' + (mod ? ',' + mod : '');
  }
};

アプリランチャー

slate.bind(util.key('r'), util.launch_and_focus('Reeder'));
slate.bind(util.key('b'), util.launch_and_focus('Safari'));
slate.bind(util.key('t'), util.launch_and_focus('iTerm'));
slate.bind(util.key('m'), util.launch_and_focus('Music'));

リサイズ・配置

細かくサイズ変更する機能は力技感ありますが
一つのキーバインドでサイクルできるのは便利です。

// m+shift    .. 最大化
slate.bind(util.key('m', 'shift'), function(win) {
  if (!win) return;
  var bounds = win.screen().visibleRect();
  win.doOperation('move', bounds);
});

// n+shift    .. タテ分割1/2サイズにする
slate.bind(util.key('n', 'shift'), slate.operation('chain', {
  operations: _.map(['left', 'right'], function(d) {
    return slate.operation('push', {
      direction: d,
      style: 'bar-resize:screenSizeX/2'
    });
  })
}));

// o+shift    .. 1/4サイズにする
slate.bind(util.key('o', 'shift'), slate.operation('chain', {
  operations: _.map(['top-left', 'top-right', 'bottom-right', 'bottom-left'], function(d) {
    return slate.operation('corner', {
      direction: d,
      width: 'screenSizeX/2',
      height: 'screenSizeY/2'
    });
  })
}));

// b+shift    .. 細かくサイズ変更
slate.bind(util.key('b', 'shift'), slate.operation('chain', {
  operations: _.map([
      {direction: 'left',  style: 'bar-resize:screenSizeX/3'},
      {direction: 'left',  style: 'bar-resize:screenSizeX/2'},
      {direction: 'left',  style: 'bar-resize:screenSizeX*2/3'},
      {direction: 'left',  style: 'bar-resize:screenSizeX'},
      {direction: 'right', style: 'bar-resize:screenSizeX*2/3'},
      {direction: 'right', style: 'bar-resize:screenSizeX/2'},
      {direction: 'right', style: 'bar-resize:screenSizeX/3'},
      {direction: 'right', style: 'bar-resize:screenSizeX/2'},
      {direction: 'right', style: 'bar-resize:screenSizeX*2/3'},
      {direction: 'left',  style: 'bar-resize:screenSizeX'},
      {direction: 'left',  style: 'bar-resize:screenSizeX*2/3'},
      {direction: 'left',  style: 'bar-resize:screenSizeX/2'}
  ], function(d) {
    return slate.operation('push', d);
  })
}));

フォーカス

// スクリーン内のウィンドウをフォーカス
slate.bind(util.key('h'), slate.operation('focus', { direction: 'left'  }));
slate.bind(util.key('j'), slate.operation('focus', { direction: 'down'  }));
slate.bind(util.key('k'), slate.operation('focus', { direction: 'up'    }));
slate.bind(util.key('l'), slate.operation('focus', { direction: 'right' }));

ウィンドウ移動

// a+shift   .. ウィンドウを左に移動
slate.bind(util.key('a', 'shift'), function(win) {
    if (!win) return;
    var rect = win.rect();
    var bounds = win.screen().visibleRect();
    rect.x -= bounds.width * 0.05;
    win.doOperation('move', rect);
});

// d+shift   .. ウィンドウを右に移動
slate.bind(util.key('d', 'shift'), function(win) {
    if (!win) return;
    var rect = win.rect();
    var bounds = win.screen().visibleRect();
    rect.x += bounds.width * 0.05;
    win.doOperation('move', rect);
});

// w+shift   .. ウィンドウを上に移動
slate.bind(util.key('w', 'shift'), function(win) {
    if (!win) return;
    var rect = win.rect();
    var bounds = win.screen().visibleRect();
    rect.y -= bounds.height * 0.05;
    win.doOperation('move', rect);
});

// s+shift   .. ウィンドウを下に移動
slate.bind(util.key('s', 'shift'), function(win) {
    if (!win) return;
    var rect = win.rect();
    var bounds = win.screen().visibleRect();
    rect.y += bounds.height * 0.05;
    win.doOperation('move', rect);
});

// f+shift    .. 次のスクリーンへ飛ばす
//slate.bind(util.key('f', 'shift'), function(win) {
//  if (!win) return;
//  var next = util.nextScreen(win.screen());
//  win.move(next.visibleRect());
//});

ウィンドウ拡大・縮小

// h+shift   .. ウィンドウが左にあるなら縮小, 右にあるなら拡大
slate.bind(util.key('h', 'shift'), function(win) {
  if (!win) return;
  var rect = win.rect();
  var bounds = win.screen().visibleRect();
  if (bounds.x + bounds.width - 30 < rect.x + rect.width) {
    rect.x -= bounds.width * 0.05;
    rect.width = bounds.x + bounds.width - rect.x;
  } else {
    rect.width -= bounds.width * 0.05;
  }
  win.doOperation('move', rect);
});

// l+shift   .. ウィンドウが右にあるなら縮小, 左にあるなら拡大
slate.bind(util.key('l', 'shift'), function(win) {
  if (!win) return;
  var rect = win.rect();
  var bounds = win.screen().visibleRect();
  if (rect.x < bounds.x + 30) {
    rect.x = bounds.x;
    rect.width += bounds.width * 0.05;
  } else {
    rect.x += bounds.width * 0.05;
    rect.width -= bounds.width * 0.05;
  }
  win.doOperation('move', rect);
});

// k+shift   .. ウィンドウが上にあるなら縮小, 下にあるなら拡大
slate.bind(util.key('k', 'shift'), function(win) {
  if (!win) return;
  var rect = win.rect();
  var bounds = win.screen().visibleRect();
  if (bounds.y + bounds.height - 30 < rect.y + rect.height) {
    rect.y -= bounds.height * 0.05;
    rect.height += bounds.height * 0.05;
  } else {
    rect.height -= bounds.height * 0.05;
  }
  win.doOperation('move', rect);
});

// j+shift   .. ウィンドウが下にあるなら縮小, 上にあるなら拡大
slate.bind(util.key('j', 'shift'), function(win) {
  if (!win) return;
  var rect = win.rect();
  var bounds = win.screen().visibleRect();
  if (rect.y < bounds.y + 30) {
    rect.y = bounds.y;
    rect.height += bounds.height * 0.05;
  } else {
    rect.y += bounds.height * 0.05;
    rect.height -= bounds.height * 0.05;
  }
  win.doOperation('move', rect);
});

おわりに

最終更新が2013年とメンテナンスされてないことが気になりますが
設定が柔軟に書けるため Mac をお使いの方にはおすすめです。
(自動で賢くレイアウトしてくれる ヤバいウィンドウマネージャ もおすすめです)

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?