├── .gitignore ├── .gitmodules ├── Gruntfile.js ├── History.md ├── Makefile ├── README.md ├── alfred-workflow ├── icon.png ├── info.plist └── layouts.scpt ├── dist ├── Layouts.alfredworkflow ├── layouts.applescript └── layouts.scpt ├── docs └── index.md ├── icon.png ├── lib ├── displays.applescript ├── layouts.applescript ├── resize.applescript ├── screens.m └── utils.applescript └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgallen23/layouts/4b27bf9202d496ad361a9af42ea89a41afafe108/.gitmodules -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | info: grunt.file.readJSON('package.json'), 4 | dist: 'dist/layouts.applescript', 5 | compiledDist: 'dist/layouts.scpt', 6 | meta: { 7 | banner: '-- <%= info.name %>\n'+ 8 | '-- v<%= info.version %>\n'+ 9 | '-- <%= info.homepage %>\n'+ 10 | '-- copyright <%= info.copyright %> <%= grunt.template.today("yyyy") %>\n'+ 11 | '-- <%= info.license %> License\n'+ 12 | '\n' 13 | }, 14 | concat: { 15 | app: { 16 | options: { 17 | banner: '<%= meta.banner %>' 18 | }, 19 | src: [ 20 | 'lib/utils.applescript', 21 | 'lib/displays.applescript', 22 | 'lib/resize.applescript', 23 | 'lib/layouts.applescript' 24 | ], 25 | dest: '<%= dist %>' 26 | } 27 | }, 28 | shell: { 29 | compile: { 30 | command: 'osacompile -o <%= compiledDist %> <%= dist %>' 31 | }, 32 | test: { 33 | command: 'osascript <%= compiledDist %> "test"', 34 | options: { 35 | stdout: true, 36 | stderr: true 37 | } 38 | }, 39 | alfred: { 40 | command: 'cp -v <%= compiledDist %> alfred-workflow/ && cp -v dist/screens alfred-workflow/', 41 | options: { 42 | stdout: true 43 | } 44 | }, 45 | alfredVersion: { 46 | command: 'sed -i "" "s/Simple Window Manager.*', 69 | tasks: ['build'] 70 | }, 71 | runTest: { 72 | files: '<%= concat.app.src %>', 73 | tasks: [ 74 | 'build', 75 | 'shell:test' 76 | ] 77 | }, 78 | screens: { 79 | files: 'lib/screens.m', 80 | tasks: [ 81 | 'shell:compileScreens', 82 | 'shell:runScreens' 83 | ] 84 | } 85 | } 86 | }); 87 | grunt.loadNpmTasks('grunt-contrib-concat'); 88 | grunt.loadNpmTasks('grunt-contrib-watch'); 89 | grunt.loadNpmTasks('grunt-shell'); 90 | 91 | grunt.registerTask('default', ['build', 'alfred']); 92 | grunt.registerTask('build', ['concat', 'shell:compile', 'shell:compileScreens']); 93 | grunt.registerTask('test', ['default', 'shell:test']); 94 | grunt.registerTask('dev', ['watch:app']); 95 | grunt.registerTask('alfred', ['shell:alfred', 'shell:alfredVersion', 'shell:alfredZip']); 96 | grunt.registerTask('dev:screens', ['watch:screens']); 97 | } 98 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 2.1.0 / 2013-05-03 3 | ================== 4 | 5 | * [grunt] runTest task 6 | * [displays] factor in dock size 7 | * Merge branch 'feature/workflow' 8 | 9 | 2.0.0 / 2013-04-17 10 | ================== 11 | 12 | * removed site submodule 13 | * [alfred] allow custom layout 14 | * [alfred] updated workflow 15 | * [grunt] added banner on top of applescript file 16 | * [alfred] build with version in description, script for zipping workflow 17 | * [alfred] updated workflow 18 | * added custom size example to alfred, added notifications 19 | * allow for passing in custom size 20 | * changed alfred bundle id 21 | * complete rewrite and initial work on alfred workflow 22 | * updated site 23 | 24 | 0.0.5 / 2012-04-19 25 | ================== 26 | 27 | * updated makefile and added DS_store to gitignore 28 | * updated alfred template 29 | * updated docs 30 | * cache screen size and fix if only one monitor 31 | 32 | Older Releases 33 | ============== 34 | 35 | * fixed some issues with multi monitors 36 | * updated site 37 | * fixed escaping chars in alfred extension 38 | * multi monitor support 39 | * moved TODO file into docs 40 | * 0.0.2 - fixed bottom 41 | * updated docs 42 | * fixed paths for docs 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: alfred site 2 | 3 | alfred: layouts.applescript 4 | @./build.py && cd alfred/out && zip tmp.zip * && mv tmp.zip ../../dist/Layouts.alfredextension 5 | @echo "Alfred Extension built" 6 | 7 | site : docs/index.md 8 | @cd site && ../node_modules/.bin/markx markx.json 9 | @echo "Site built" 10 | 11 | preview-site: 12 | @cd site && ../node_modules/.bin/markx --preview 8001 markx.json 13 | 14 | preview-readme: 15 | @./node_modules/.bin/markx --preview 8001 README.md 16 | 17 | install: node_modules/markx 18 | git submodule update --init 19 | @cd site && git submodule update --init 20 | 21 | node_modules/markx: 22 | npm install markx 23 | 24 | .PHONY: preview-docs preview-readme 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Layouts 2 | 3 | Layouts is an applescript and an [alfred](http://www.alfredapp.com/) extension to easily move and resize application windows. 4 | 5 | Go [here](http://projects.jga.me/layouts/) for more info. 6 | -------------------------------------------------------------------------------- /alfred-workflow/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgallen23/layouts/4b27bf9202d496ad361a9af42ea89a41afafe108/alfred-workflow/icon.png -------------------------------------------------------------------------------- /alfred-workflow/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | jga.alfred.layouts 7 | connections 8 | 9 | 2D9B5608-8924-44BB-ACE3-06F124842A7D 10 | 11 | 12 | destinationuid 13 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 14 | modifiers 15 | 0 16 | modifiersubtext 17 | 18 | 19 | 20 | 3761243B-89C7-4838-8FBA-F867461E846B 21 | 22 | 23 | destinationuid 24 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 25 | modifiers 26 | 0 27 | modifiersubtext 28 | 29 | 30 | 31 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 32 | 33 | 4BBD7242-BD9D-4D8E-98F9-CB61E3FC3F39 34 | 35 | 36 | destinationuid 37 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 38 | modifiers 39 | 0 40 | modifiersubtext 41 | 42 | 43 | 44 | 58E90636-73B4-4C00-A127-681D45272BF0 45 | 46 | 47 | destinationuid 48 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 49 | modifiers 50 | 0 51 | modifiersubtext 52 | 53 | 54 | 55 | 5B360532-D9CC-4FE9-93FB-75AF82787F4E 56 | 57 | 58 | destinationuid 59 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 60 | modifiers 61 | 0 62 | modifiersubtext 63 | 64 | 65 | 66 | 6FB3D7CB-E570-4171-8B47-B187079B14FD 67 | 68 | 69 | destinationuid 70 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 71 | modifiers 72 | 0 73 | modifiersubtext 74 | 75 | 76 | 77 | 7BEAB15D-9856-4ABD-AC0A-ACAC34A14F8D 78 | 79 | 80 | destinationuid 81 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 82 | modifiers 83 | 0 84 | modifiersubtext 85 | 86 | 87 | 88 | 9A1C878F-2C40-4803-BF6D-3A4B00BB17DB 89 | 90 | 91 | destinationuid 92 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 93 | modifiers 94 | 0 95 | modifiersubtext 96 | 97 | 98 | 99 | A4ED796E-D87A-4F4E-9CC0-07A67EAFC2C5 100 | 101 | 102 | destinationuid 103 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 104 | modifiers 105 | 0 106 | modifiersubtext 107 | 108 | 109 | 110 | B35E46CC-D76A-4961-B412-23E2297299F1 111 | 112 | 113 | destinationuid 114 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 115 | modifiers 116 | 0 117 | modifiersubtext 118 | 119 | 120 | 121 | D492AA39-6473-48DF-8C81-88FBEEC71368 122 | 123 | 124 | destinationuid 125 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 126 | modifiers 127 | 0 128 | modifiersubtext 129 | 130 | 131 | 132 | E1455114-F18E-455A-B9E7-4F66E1A51C1F 133 | 134 | 135 | destinationuid 136 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 137 | modifiers 138 | 0 139 | modifiersubtext 140 | 141 | 142 | 143 | E916DFF6-3FE6-4FFD-BB58-4712FDA62E6F 144 | 145 | 146 | destinationuid 147 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 148 | modifiers 149 | 0 150 | modifiersubtext 151 | 152 | 153 | 154 | F4897C6D-A35C-467D-93C6-690D11710ED9 155 | 156 | 157 | destinationuid 158 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 159 | modifiers 160 | 0 161 | modifiersubtext 162 | 163 | 164 | 165 | 166 | createdby 167 | JGAui 168 | description 169 | Simple Window Manager v2.1.0 170 | disabled 171 | 172 | name 173 | Layouts 174 | objects 175 | 176 | 177 | config 178 | 179 | argumenttype 180 | 0 181 | keyword 182 | layouts 183 | subtext 184 | Resize Current Window 185 | text 186 | Layouts 187 | withspace 188 | 189 | 190 | type 191 | alfred.workflow.input.keyword 192 | uid 193 | E916DFF6-3FE6-4FFD-BB58-4712FDA62E6F 194 | 195 | 196 | config 197 | 198 | action 199 | 0 200 | argument 201 | 3 202 | argumenttext 203 | left 204 | hotkey 205 | 123 206 | hotmod 207 | 12451840 208 | hotstring 209 | 210 | leftcursor 211 | 212 | modsmode 213 | 0 214 | 215 | type 216 | alfred.workflow.trigger.hotkey 217 | uid 218 | A4ED796E-D87A-4F4E-9CC0-07A67EAFC2C5 219 | 220 | 221 | config 222 | 223 | action 224 | 0 225 | argument 226 | 3 227 | argumenttext 228 | right 229 | hotkey 230 | 124 231 | hotmod 232 | 12451840 233 | hotstring 234 | 235 | leftcursor 236 | 237 | modsmode 238 | 0 239 | 240 | type 241 | alfred.workflow.trigger.hotkey 242 | uid 243 | 2D9B5608-8924-44BB-ACE3-06F124842A7D 244 | 245 | 246 | config 247 | 248 | action 249 | 0 250 | argument 251 | 3 252 | argumenttext 253 | top 254 | hotkey 255 | 126 256 | hotmod 257 | 12451840 258 | hotstring 259 | 260 | leftcursor 261 | 262 | modsmode 263 | 0 264 | 265 | type 266 | alfred.workflow.trigger.hotkey 267 | uid 268 | 5B360532-D9CC-4FE9-93FB-75AF82787F4E 269 | 270 | 271 | config 272 | 273 | action 274 | 0 275 | argument 276 | 3 277 | argumenttext 278 | bottom 279 | hotkey 280 | 125 281 | hotmod 282 | 12451840 283 | hotstring 284 | 285 | leftcursor 286 | 287 | modsmode 288 | 0 289 | 290 | type 291 | alfred.workflow.trigger.hotkey 292 | uid 293 | 6FB3D7CB-E570-4171-8B47-B187079B14FD 294 | 295 | 296 | config 297 | 298 | action 299 | 0 300 | argument 301 | 3 302 | argumenttext 303 | zoom 304 | hotkey 305 | 6 306 | hotmod 307 | 1966080 308 | hotstring 309 | Z 310 | leftcursor 311 | 312 | modsmode 313 | 0 314 | 315 | type 316 | alfred.workflow.trigger.hotkey 317 | uid 318 | 3761243B-89C7-4838-8FBA-F867461E846B 319 | 320 | 321 | config 322 | 323 | escaping 324 | 62 325 | script 326 | osascript layouts.scpt "{query}" 327 | type 328 | 0 329 | 330 | type 331 | alfred.workflow.action.script 332 | uid 333 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 334 | 335 | 336 | config 337 | 338 | action 339 | 0 340 | argument 341 | 3 342 | argumenttext 343 | center 344 | hotkey 345 | 8 346 | hotmod 347 | 1966080 348 | hotstring 349 | C 350 | leftcursor 351 | 352 | modsmode 353 | 0 354 | 355 | type 356 | alfred.workflow.trigger.hotkey 357 | uid 358 | F4897C6D-A35C-467D-93C6-690D11710ED9 359 | 360 | 361 | config 362 | 363 | action 364 | 0 365 | argument 366 | 3 367 | argumenttext 368 | centersmall 369 | hotkey 370 | 7 371 | hotmod 372 | 1966080 373 | hotstring 374 | X 375 | leftcursor 376 | 377 | modsmode 378 | 0 379 | 380 | type 381 | alfred.workflow.trigger.hotkey 382 | uid 383 | B35E46CC-D76A-4961-B412-23E2297299F1 384 | 385 | 386 | config 387 | 388 | action 389 | 0 390 | argument 391 | 3 392 | argumenttext 393 | topleft 394 | hotkey 395 | 18 396 | hotmod 397 | 1966080 398 | hotstring 399 | ! 400 | leftcursor 401 | 402 | modsmode 403 | 0 404 | 405 | type 406 | alfred.workflow.trigger.hotkey 407 | uid 408 | 7BEAB15D-9856-4ABD-AC0A-ACAC34A14F8D 409 | 410 | 411 | config 412 | 413 | action 414 | 0 415 | argument 416 | 3 417 | argumenttext 418 | topright 419 | hotkey 420 | 19 421 | hotmod 422 | 1966080 423 | hotstring 424 | @ 425 | leftcursor 426 | 427 | modsmode 428 | 0 429 | 430 | type 431 | alfred.workflow.trigger.hotkey 432 | uid 433 | 58E90636-73B4-4C00-A127-681D45272BF0 434 | 435 | 436 | config 437 | 438 | action 439 | 0 440 | argument 441 | 3 442 | argumenttext 443 | bottomleft 444 | hotkey 445 | 20 446 | hotmod 447 | 1966080 448 | hotstring 449 | # 450 | leftcursor 451 | 452 | modsmode 453 | 0 454 | 455 | type 456 | alfred.workflow.trigger.hotkey 457 | uid 458 | 4BBD7242-BD9D-4D8E-98F9-CB61E3FC3F39 459 | 460 | 461 | config 462 | 463 | action 464 | 0 465 | argument 466 | 3 467 | argumenttext 468 | bottomright 469 | hotkey 470 | 21 471 | hotmod 472 | 1966080 473 | hotstring 474 | $ 475 | leftcursor 476 | 477 | modsmode 478 | 0 479 | 480 | type 481 | alfred.workflow.trigger.hotkey 482 | uid 483 | E1455114-F18E-455A-B9E7-4F66E1A51C1F 484 | 485 | 486 | config 487 | 488 | action 489 | 0 490 | argument 491 | 3 492 | argumenttext 493 | 0 0 .4 1 494 | hotkey 495 | 41 496 | hotmod 497 | 1966080 498 | hotstring 499 | : 500 | leftcursor 501 | 502 | modsmode 503 | 0 504 | 505 | type 506 | alfred.workflow.trigger.hotkey 507 | uid 508 | D492AA39-6473-48DF-8C81-88FBEEC71368 509 | 510 | 511 | config 512 | 513 | action 514 | 0 515 | argument 516 | 3 517 | argumenttext 518 | .4 0 1 1 519 | hotkey 520 | 39 521 | hotmod 522 | 1966080 523 | hotstring 524 | " 525 | leftcursor 526 | 527 | modsmode 528 | 0 529 | 530 | type 531 | alfred.workflow.trigger.hotkey 532 | uid 533 | 9A1C878F-2C40-4803-BF6D-3A4B00BB17DB 534 | 535 | 536 | readme 537 | 538 | uidata 539 | 540 | 2D9B5608-8924-44BB-ACE3-06F124842A7D 541 | 542 | ypos 543 | 280 544 | 545 | 3761243B-89C7-4838-8FBA-F867461E846B 546 | 547 | ypos 548 | 640 549 | 550 | 4A3C9A90-372E-404D-AF8F-53F3F4FA6F61 551 | 552 | ypos 553 | 760 554 | 555 | 4BBD7242-BD9D-4D8E-98F9-CB61E3FC3F39 556 | 557 | ypos 558 | 1240 559 | 560 | 58E90636-73B4-4C00-A127-681D45272BF0 561 | 562 | ypos 563 | 1120 564 | 565 | 5B360532-D9CC-4FE9-93FB-75AF82787F4E 566 | 567 | ypos 568 | 400 569 | 570 | 6FB3D7CB-E570-4171-8B47-B187079B14FD 571 | 572 | ypos 573 | 520 574 | 575 | 7BEAB15D-9856-4ABD-AC0A-ACAC34A14F8D 576 | 577 | ypos 578 | 1000 579 | 580 | 9A1C878F-2C40-4803-BF6D-3A4B00BB17DB 581 | 582 | ypos 583 | 1600 584 | 585 | A4ED796E-D87A-4F4E-9CC0-07A67EAFC2C5 586 | 587 | ypos 588 | 160 589 | 590 | B35E46CC-D76A-4961-B412-23E2297299F1 591 | 592 | ypos 593 | 880 594 | 595 | D492AA39-6473-48DF-8C81-88FBEEC71368 596 | 597 | ypos 598 | 1480 599 | 600 | E1455114-F18E-455A-B9E7-4F66E1A51C1F 601 | 602 | ypos 603 | 1360 604 | 605 | E916DFF6-3FE6-4FFD-BB58-4712FDA62E6F 606 | 607 | ypos 608 | 10 609 | 610 | F4897C6D-A35C-467D-93C6-690D11710ED9 611 | 612 | ypos 613 | 760 614 | 615 | 616 | webaddress 617 | http://twitter.com/jgaui 618 | 619 | 620 | -------------------------------------------------------------------------------- /alfred-workflow/layouts.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgallen23/layouts/4b27bf9202d496ad361a9af42ea89a41afafe108/alfred-workflow/layouts.scpt -------------------------------------------------------------------------------- /dist/Layouts.alfredworkflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgallen23/layouts/4b27bf9202d496ad361a9af42ea89a41afafe108/dist/Layouts.alfredworkflow -------------------------------------------------------------------------------- /dist/layouts.applescript: -------------------------------------------------------------------------------- 1 | -- Layouts 2 | -- v2.1.0 3 | -- http://projects.jga.me/layouts 4 | -- copyright JGA 2013 5 | -- MIT License 6 | 7 | 8 | on explode(delimiter, input) 9 | local delimiter, input, ASTID 10 | set ASTID to AppleScript's text item delimiters 11 | try 12 | set AppleScript's text item delimiters to delimiter 13 | set input to text items of input 14 | set AppleScript's text item delimiters to ASTID 15 | return input --> list 16 | on error eMsg number eNum 17 | set AppleScript's text item delimiters to ASTID 18 | error "Can't explode: " & eMsg number eNum 19 | end try 20 | end explode 21 | 22 | 23 | on getDisplayBounds() 24 | --TODO: multi monitor support 25 | tell application "Finder" 26 | set scrRes to bounds of window of desktop 27 | end tell 28 | tell application "System Events" 29 | tell dock preferences 30 | set dockProperties to get properties 31 | end tell 32 | 33 | if autohide of dockProperties is false then 34 | tell process "Dock" 35 | set dockDimensions to size in list 1 36 | set dockWidth to item 1 of dockDimensions 37 | set dockHeight to item 2 of dockDimensions 38 | end tell 39 | set screenEdge to screen edge of dockProperties 40 | if screenEdge is bottom then 41 | set item 4 of scrRes to (item 4 of scrRes) - dockHeight 42 | else if screenEdge is left then 43 | set item 1 of scrRes to dockWidth 44 | set item 4 of scrRes to (item 4 of scrRes) - dockWidth 45 | else if screenEdge is right then 46 | set item 3 of scrRes to (item 3 of scrRes) - dockWidth 47 | end if 48 | end if 49 | end tell 50 | 51 | return scrRes 52 | end getDisplayBounds 53 | 54 | 55 | on makeLayout(_name, _key, x1, y1, x2, y2) 56 | script layout 57 | property theName : _name 58 | property theKey : _key 59 | property x1Percentage : x1 60 | property y1Percentage : y1 61 | property x2Percentage : x2 62 | property y2Percentage : y2 63 | end script 64 | return layout 65 | end makeLayout 66 | 67 | on makeDefaultLayouts() 68 | 69 | set topLeft to makeLayout("Top Left", "topleft", 0, 0, 0.5, 0.5) 70 | set topRight to makeLayout("Top Right", "topright", 0.5, 0, 1, 0.5) 71 | set bottomLeft to makeLayout("Bottom Left", "bottomleft", 0, 0.5, 0.5, 1) 72 | set bottomRight to makeLayout("Bottom Right", "bottomright", 0.5, 0.5, 1.0, 1) 73 | set top to makeLayout("Top", "top", 0, 0, 1, .5) 74 | set bottom to makeLayout("Bottom", "bottom", 0, .5, 1, 1) 75 | set _left to makeLayout("Left", "left", 0, 0, 0.5, 1) 76 | set _right to makeLayout("Right", "right", .5, 0, 1, 1) 77 | set zoom to makeLayout("Zoom", "zoom", 0, 0, 1, 1) 78 | set centerLarge to makeLayout("Center Large", "center", 0.1, 0.1, 0.9, 0.9) 79 | set centerSmall to makeLayout("Center Small", "centersmall", 0.3, 0.3, 0.7, 0.7) 80 | 81 | set layouts to { topLeft, topRight, bottomRight, bottomLeft, top, _right, bottom, _left, centerLarge, centerSmall, zoom } 82 | 83 | return layouts 84 | 85 | end makeDefaultLayouts 86 | 87 | on findLayout(layouts, layoutKey) 88 | 89 | set foundLayout to false 90 | repeat with layout in layouts 91 | set _key to get theKey of layout 92 | if layoutKey is _key then 93 | set foundLayout to layout 94 | end if 95 | end repeat 96 | return foundLayout 97 | 98 | end findLayout 99 | 100 | on resize(theApp, theScreenBounds, theLayout) 101 | 102 | tell application theApp 103 | set appBounds to bounds of window 1 104 | set sx to item 1 of theScreenBounds 105 | set sy to item 2 of theScreenBounds 106 | set sw to (item 3 of theScreenBounds) - sx 107 | set sh to (item 4 of theScreenBounds) - sy 108 | set x1 to sx + (sw * (x1Percentage of theLayout)) 109 | set y1 to sy + (sh * (y1Percentage of theLayout)) 110 | set x2 to sx + (sw * (x2Percentage of theLayout)) 111 | set y2 to sy + (sh * (y2Percentage of theLayout)) 112 | activate 113 | set bounds of window 1 to { x1, y1, x2, y2 } 114 | end tell 115 | end resize 116 | 117 | on testLayouts(theApp, screenBounds) 118 | set layouts to makeDefaultLayouts() 119 | repeat with layout in layouts 120 | resize(theApp, screenBounds, layout) 121 | delay 0.5 122 | end repeat 123 | end testLayouts 124 | 125 | 126 | on run argv 127 | 128 | set theApp to (path to frontmost application as Unicode text) 129 | set screenBounds to getDisplayBounds() 130 | 131 | set theLayoutKey to item 1 of argv 132 | 133 | if theLayoutKey is "test" then 134 | testLayouts(theApp, screenBounds) 135 | else 136 | set layouts to makeDefaultLayouts() 137 | set layout to findLayout(layouts, theLayoutKey) 138 | 139 | if layout is false then 140 | set sizes to explode(" ", theLayoutKey) 141 | set layout to makeLayout("Temp", "tmp", (item 1 of sizes), (item 2 of sizes), (item 3 of sizes), (item 4 of sizes)) 142 | end if 143 | resize(theApp, screenBounds, layout) 144 | end if 145 | 146 | 147 | 148 | end run 149 | -------------------------------------------------------------------------------- /dist/layouts.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgallen23/layouts/4b27bf9202d496ad361a9af42ea89a41afafe108/dist/layouts.scpt -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Layouts 2 | 3 | Layouts is an applescript and an [alfred](http://www.alfredapp.com/) extension to easily move and resize application windows. 4 | 5 | ![Example Layout](ui/layouts.jpg) 6 | 7 | ##Alfred 8 | 9 | You can download the alfred extension [here](https://github.com/jgallen23/layouts/raw/master/dist/Layouts.alfredextension). 10 | 11 | ###Command 12 | - resize [f, t, b, l, r, tl, tr, bl, br, c, m, reset] 13 | 14 | ###Layouts 15 | - f: full screen 16 | - c: center window 17 | - t: top half of screen 18 | - b: bottom half of screen 19 | - l: left half of screen 20 | - r: right half of screen 21 | - tl: top left quarter of screen 22 | - tr: top right quarter of screen 23 | - bl: bottom left quarter of screen 24 | - br: bottom right quarter of screen 25 | - m: move to next monitor 26 | - reset: recalculate screen size 27 | 28 | ###Hotkey support 29 | Thanks to Alfred's new hotkey feature, you don't even have to trigger alfred to move your windows around. 30 | 31 | ![Hotkeys](ui/layouts-hotkeys.jpg) 32 | 33 | ##Applescript 34 | 35 | Go [here](https://raw.github.com/jgallen23/layouts/master/layouts.applescript) to view the script. 36 | 37 | ###Command Line 38 | The script will work via the command line too! *Make sure to uncomment the on run argv lines if you want to use it this way* 39 | 40 | osascript layouts.applescript f 41 | 42 | 43 | ##History 44 | 45 | ####0.0.5 (04/19/2012) 46 | - cached screen size so layouts will run much faster 47 | - fixed some issues with single monitor setups 48 | 49 | ####0.0.4 (03/19/2012) 50 | - fixed a few bugs in the multi monitor support 51 | 52 | ####0.0.3 (03/18/2012) 53 | - multi monitor support 54 | 55 | ####0.0.2 56 | - bug fixes 57 | 58 | ####0.0.1 59 | - initial release 60 | 61 | ##Future 62 | - automatic update support 63 | - custom sizes 64 | 65 | ##Contributors 66 | - Greg Allen ([@jgaui](http://twitter.com/jgaui)) [jga.me](http://jga.me) 67 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgallen23/layouts/4b27bf9202d496ad361a9af42ea89a41afafe108/icon.png -------------------------------------------------------------------------------- /lib/displays.applescript: -------------------------------------------------------------------------------- 1 | 2 | on getScreens() 3 | set tmp to do shell script "PWD" 4 | set myPath to POSIX path of (path to me) as string 5 | set dirname to (do shell script "dirname \"" & myPath & "\"") as string 6 | 7 | set scrString to do shell script "\"" & dirname & "/screens\"" 8 | set scrRes to explode(",", scrString) 9 | 10 | return scrRes 11 | end getScreens 12 | 13 | on getDisplayBounds() 14 | --TODO: multi monitor support 15 | set scrRes to getScreens() 16 | tell application "System Events" 17 | tell dock preferences 18 | set dockProperties to get properties 19 | end tell 20 | 21 | if autohide of dockProperties is false then 22 | tell process "Dock" 23 | set dockDimensions to size in list 1 24 | set dockWidth to item 1 of dockDimensions 25 | set dockHeight to item 2 of dockDimensions 26 | end tell 27 | set screenEdge to screen edge of dockProperties 28 | if screenEdge is bottom then 29 | set item 4 of scrRes to (item 4 of scrRes) - dockHeight 30 | else if screenEdge is left then 31 | set item 1 of scrRes to dockWidth 32 | set item 4 of scrRes to (item 4 of scrRes) - dockWidth 33 | else if screenEdge is right then 34 | set item 3 of scrRes to (item 3 of scrRes) - dockWidth 35 | end if 36 | end if 37 | end tell 38 | 39 | return scrRes 40 | end getDisplayBounds 41 | 42 | -------------------------------------------------------------------------------- /lib/layouts.applescript: -------------------------------------------------------------------------------- 1 | 2 | on run argv 3 | 4 | set theApp to (path to frontmost application as Unicode text) 5 | set screenBounds to getDisplayBounds() 6 | 7 | set theLayoutKey to item 1 of argv 8 | 9 | if theLayoutKey is "test" then 10 | testLayouts(theApp, screenBounds) 11 | else 12 | set layouts to makeDefaultLayouts() 13 | set layout to findLayout(layouts, theLayoutKey) 14 | 15 | if layout is false then 16 | set sizes to explode(" ", theLayoutKey) 17 | set layout to makeLayout("Temp", "tmp", (item 1 of sizes), (item 2 of sizes), (item 3 of sizes), (item 4 of sizes)) 18 | end if 19 | resize(theApp, screenBounds, layout) 20 | end if 21 | 22 | 23 | 24 | end run 25 | -------------------------------------------------------------------------------- /lib/resize.applescript: -------------------------------------------------------------------------------- 1 | 2 | on makeLayout(_name, _key, x1, y1, x2, y2) 3 | script layout 4 | property theName : _name 5 | property theKey : _key 6 | property x1Percentage : x1 7 | property y1Percentage : y1 8 | property x2Percentage : x2 9 | property y2Percentage : y2 10 | end script 11 | return layout 12 | end makeLayout 13 | 14 | on makeDefaultLayouts() 15 | 16 | set topLeft to makeLayout("Top Left", "topleft", 0, 0, 0.5, 0.5) 17 | set topRight to makeLayout("Top Right", "topright", 0.5, 0, 1, 0.5) 18 | set bottomLeft to makeLayout("Bottom Left", "bottomleft", 0, 0.5, 0.5, 1) 19 | set bottomRight to makeLayout("Bottom Right", "bottomright", 0.5, 0.5, 1.0, 1) 20 | set top to makeLayout("Top", "top", 0, 0, 1, .5) 21 | set bottom to makeLayout("Bottom", "bottom", 0, .5, 1, 1) 22 | set _left to makeLayout("Left", "left", 0, 0, 0.5, 1) 23 | set _right to makeLayout("Right", "right", .5, 0, 1, 1) 24 | set zoom to makeLayout("Zoom", "zoom", 0, 0, 1, 1) 25 | set centerLarge to makeLayout("Center Large", "center", 0.1, 0.1, 0.9, 0.9) 26 | set centerSmall to makeLayout("Center Small", "centersmall", 0.3, 0.3, 0.7, 0.7) 27 | 28 | set layouts to { topLeft, topRight, bottomRight, bottomLeft, top, _right, bottom, _left, centerLarge, centerSmall, zoom } 29 | 30 | return layouts 31 | 32 | end makeDefaultLayouts 33 | 34 | on findLayout(layouts, layoutKey) 35 | 36 | set foundLayout to false 37 | repeat with layout in layouts 38 | set _key to get theKey of layout 39 | if layoutKey is _key then 40 | set foundLayout to layout 41 | end if 42 | end repeat 43 | return foundLayout 44 | 45 | end findLayout 46 | 47 | on resize(theApp, theScreenBounds, theLayout) 48 | 49 | tell application theApp 50 | set appBounds to bounds of window 1 51 | set sx to item 1 of theScreenBounds 52 | set sy to item 2 of theScreenBounds 53 | set sw to (item 3 of theScreenBounds) - sx 54 | set sh to (item 4 of theScreenBounds) - sy 55 | set x1 to sx + (sw * (x1Percentage of theLayout)) 56 | set y1 to sy + (sh * (y1Percentage of theLayout)) 57 | set x2 to sx + (sw * (x2Percentage of theLayout)) 58 | set y2 to sy + (sh * (y2Percentage of theLayout)) 59 | activate 60 | set bounds of window 1 to { x1, y1, x2, y2 } 61 | end tell 62 | end resize 63 | 64 | on testLayouts(theApp, screenBounds) 65 | set layouts to makeDefaultLayouts() 66 | repeat with layout in layouts 67 | resize(theApp, screenBounds, layout) 68 | delay 0.5 69 | end repeat 70 | end testLayouts 71 | -------------------------------------------------------------------------------- /lib/screens.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | 5 | int main(int argc, const char * argv[]) { 6 | 7 | 8 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 9 | 10 | //NSArray *screens = [NSScreen screens]; 11 | 12 | NSScreen *mainScreen = [NSScreen mainScreen]; 13 | 14 | NSRect rect = mainScreen.frame; 15 | NSString *out = [NSString stringWithFormat:@"%1.0f,%1.0f,%1.0f,%1.0f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height]; 16 | 17 | const char *str = [out UTF8String]; 18 | printf(str); 19 | 20 | // insert code here... 21 | //NSLog(@"%@", [screens objectAtIndex:0]); 22 | 23 | //for (NSScreen *screen in screens) { 24 | //NSLog(@"%@", NSStringFromRect(screen.frame)); 25 | //NSString *str = NSStringFromRect(screen.frame); 26 | //printf([str UTF8String]); 27 | //} 28 | 29 | //NSRunningApplication *activeApplication = nil; 30 | //for (NSRunningApplication *app in [[NSWorkspace sharedWorkspace] runningApplications]) { 31 | //if (app.active) { 32 | //activeApplication = app; 33 | //break; 34 | //} 35 | //} 36 | 37 | [pool drain]; 38 | return 0; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /lib/utils.applescript: -------------------------------------------------------------------------------- 1 | 2 | on explode(delimiter, input) 3 | local delimiter, input, ASTID 4 | set ASTID to AppleScript's text item delimiters 5 | try 6 | set AppleScript's text item delimiters to delimiter 7 | set input to text items of input 8 | set AppleScript's text item delimiters to ASTID 9 | return input --> list 10 | on error eMsg number eNum 11 | set AppleScript's text item delimiters to ASTID 12 | error "Can't explode: " & eMsg number eNum 13 | end try 14 | end explode 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Layouts", 3 | "private": true, 4 | "version": "2.1.0", 5 | "homepage": "http://projects.jga.me/layouts", 6 | "copyright": "JGA", 7 | "license": "MIT", 8 | "devDependencies": { 9 | "grunt-shell": "~0.2.1", 10 | "grunt-contrib-concat": "~0.1.3", 11 | "grunt": "~0.4.1", 12 | "grunt-contrib-watch": "~0.3.1" 13 | } 14 | } 15 | --------------------------------------------------------------------------------