Skip to content

Instantly share code, notes, and snippets.

@pxeger
Created December 2, 2021 19:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pxeger/234601487ce4190da4b5a212bdc8eb28 to your computer and use it in GitHub Desktop.
Save pxeger/234601487ce4190da4b5a212bdc8eb28 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Ideal monitor rotation for programmers</title>
<meta name="description" content="xssfox is hacking on cursed software, hardware and everything in between." />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="alternate"
type="application/rss+xml"
href="https://sprocketfox.io/xssfox/index.xml"
title="xssfox"
/>
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image" content="https://sprocketfox.io/xssfox/android-chrome-512x512.png"/>
<meta name="twitter:title" content="Ideal monitor rotation for programmers"/>
<meta name="twitter:description" content="How to be a pro programmer"/>
<link rel="stylesheet" href="https://sprocketfox.io/xssfox/fontawesome/css/all.min.css" />
<link rel="stylesheet" href="https://sprocketfox.io/xssfox/fixes.css" />
<link
id="dark-mode-theme"
rel="stylesheet"
href="https://sprocketfox.io/xssfox/css/dark.css"
/>
<script>
var darkTheme = document.getElementById('dark-mode-theme')
var storedTheme = localStorage.getItem('dark-mode-storage')
if (storedTheme === 'dark') {
darkTheme.disabled = false
} else if (storedTheme === 'light') {
darkTheme.disabled = true
}
</script>
<script src="https://sprocketfox.io/xssfox/js/bundle.js"></script>
<script src="https://sprocketfox.io/xssfox/js/instantpage.min.js" type="module" defer></script>
<meta name="generator" content="Hugo 0.89.4" /><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
</head>
<body>
<header>
<nav class="navbar">
<div class="nav">
<a href="https://sprocketfox.io/xssfox/" class="nav-logo">
<img
src="https://sprocketfox.io/xssfox/images/icon.png"
width="50"
height="50"
alt="Logo"
/>
</a>
<ul class="nav-links">
<li>
<a href="/xssfox/about/" aria-label="About" id="About"
><em aria-hidden="true" class="fas fa-user fa-lg"></em
></a>
</li>
<li>
<a href="/xssfox/archives" aria-label="Archives" id="Archives"
><em aria-hidden="true" class="fas fa-archive fa-lg"></em
></a>
</li>
<li>
<a href="/xssfox/search" aria-label="Search" id="Search"
><em aria-hidden="true" class="fas fa-search fa-lg"></em
></a>
</li>
</ul>
</div>
</nav>
<div class="intro-header">
<div class="container">
<div class="post-heading">
<h1>
Ideal monitor rotation for programmers
</h1>
<span class="meta-post">
<em class="fa fa-calendar-alt"></em
>&nbsp;Dec 2, 2021
</span>
</div>
</div>
</div>
</header>
<div class="container" role="main">
<article class="article" class="blog-post">
<p><img src="/xssfox/images/PXL_20211202_033906006.jpg" alt="Monitor in landscape mode"></p>
<p>It all started with this toot from <a href="https://cloudisland.nz/web/accounts/1">Aurynn</a>.</p>
<iframe src="https://cloudisland.nz/@aurynn/107373660689062982/embed" class="mastodon-embed" style="max-width: 100%;margin: auto; border: 0;display:block;" width="400" allowfullscreen="allowfullscreen"></iframe><script src="https://cloudisland.nz/embed.js" async="async"></script>
<blockquote>
<p>do I just need to put one screen in portrait mode?</p>
</blockquote>
<p>In the past I had experimented with using portrait displays for reading and programming. The ability to display large amount of text is certainly appealing.</p>
<h3 id="boring">Boring</h3>
<p><img src="/xssfox/images/PXL_20211202_034116753.jpg" alt="Monitor in portrait mode"></p>
<p>But is this the most optimal display for software development? Lets evaluate</p>
<table>
<thead>
<tr>
<th>Rotation</th>
<th>Advantages</th>
<th>Disadvantages</th>
</tr>
</thead>
<tbody>
<tr>
<td>0°</td>
<td>Works with most applications. Video content is usually in wide format</td>
<td>Websites and documents usually end up with a lot of whitespace and padding around them</td>
</tr>
<tr>
<td>90°</td>
<td>Great for text documents - can read down like a book page</td>
<td>Movies don&rsquo;t display well. Viewing angle problems</td>
</tr>
</tbody>
</table>
<p>Here you might think we might done. But there are soooooo many more angles we can try. This is a little tricky on macOS and Windows but on Linux we have all the freedom we need.</p>
<h3 id="odd-but-ok">Odd but ok.</h3>
<p>We have a little tool called <code>xrandr</code> (x resize and rotate). We can use it to rotate the screen around to any angle we want. In practice I couldn&rsquo;t get this to work on my MacBook. My desktop on the otherhand it had no problems. So lets try a few out.</p>
<p><img src="/xssfox/images/PXL_20211202_034333303.jpg" alt="Monitor with a 1 degree rotation"></p>
<blockquote>
<p>1° - notice the menu bar disappearing to the right</p>
</blockquote>
<p><img src="/xssfox/images/PXL_20211202_034744788.jpg" alt="Monitor with a 45 degree rotation"></p>
<blockquote>
<p>45° - I run out of space</p>
</blockquote>
<table>
<thead>
<tr>
<th>Rotation</th>
<th>Advantages</th>
<th>Disadvantages</th>
</tr>
</thead>
<tbody>
<tr>
<td>1°</td>
<td>Handy if your desk is on a slight slope</td>
<td>fonts render a little weird</td>
</tr>
<tr>
<td>45°</td>
<td>Middle ground between vertical and horizontal</td>
<td>doesn&rsquo;t fit well with non square aspect ratios</td>
</tr>
</tbody>
</table>
<p>One neat thing about 45° is that it gives us pretty close to the diagonal. But not on my ultra wide. Due to maths, the amount we&rsquo;d need to rotate is based on the angle of a triangle which match the aspect ration of the screen we are using. This ends up being about 22° for a 21:9 ratio.</p>
<h3 id="the-perfect-rotation">The perfect rotation</h3>
<p><img src="/xssfox/images/PXL_20211202_035205492.jpg" alt="Monitor with a 22 degree rotation"></p>
<blockquote>
<p>22° - Perfect</p>
</blockquote>
<table>
<thead>
<tr>
<th>Rotation</th>
<th>Advantages</th>
<th>Disadvantages</th>
</tr>
</thead>
<tbody>
<tr>
<td>22°</td>
<td>Longest line length!</td>
<td>Webcam starts sliding away</td>
</tr>
</tbody>
</table>
<p>So this here I think is the best monitor orientation for software development. It provides the longest line lengths and no longer need to worry about that pesky 80 column limit.</p>
<h3 id="how-do-i-do-this">How do I do this?</h3>
<p>First off, I could only get this to work in xorg - no wayland support yet. <code>xrandr --output HDMI-3 --transform lots of numbers here</code> takes a transformation matrix thats used to position the screen. We can use that to rotate the display.</p>
<p>The basic syntax that we need for rotating and shifting is this</p>
<pre tabindex="0"><code>cos(x),-sin(x),shift_left,sin(x),cos(x),shift_up,0,0,1
</code></pre><p>Some examples</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#75715e"># these won&#39;t shift / center the display as I don&#39;t know the resolution</span>
<span style="color:#75715e">#-0.1</span>
xrandr --output HDMI-3 --transform 0.999998476913288,0.00174532836589831,0,-0.00174532836589831,0.999998476913288,0,0,0,1
<span style="color:#75715e">#1</span>
xrandr --output HDMI-3 --transform 0.999847695156391,-0.0174524064372835,0,0.0174524064372835,0.999847695156391,0,0,0,1
<span style="color:#75715e">#45</span>
xrandr --output HDMI-3 --transform 0.707106781186548,-0.707106781186548,0,0.707106781186548,0.707106781186548,0,0,0,1
<span style="color:#75715e">#22</span>
xrandr --output HDMI-3 --transform 0.927183854566787,-0.374606593415912,0,0.374606593415912,0.927183854566787,0,0,0,1
</code></pre></div><h4 id="calculator">Calculator</h4>
<p>This little javascript calculator should generate the xrandr command for given inputs</p>
<form action="javascript:void(0);">
<table border="1" cellpadding="10px" cellspacing="5px">
<tr><td>Input: </td><td><input class="xrandr_calc" id="display-input" placeholder="Input Name (eg HDMI-1" value="HDMI-1"></td></tr>
<tr><td>Angle: </td><td><input class="xrandr_calc" id="angle" placeholder="Angle" type="number" value=45></td></tr>
<tr><td>Shift X: </td><td><input class="xrandr_calc" id="shiftx" placeholder="Shift X" value=0></td></tr>
<tr><td>Shift Y: </td><td><input class="xrandr_calc" id="shifty" placeholder="Shift Y" value=0></td></tr>
<tr><td></td><td></td></tr>
<tr><td><b>Result: </b></td><td id=result></td></tr>
</table>
</form>
<script>
function update_xrandr(){
var angle = document.getElementById("angle").value
var a=Math.cos(angle * (Math.PI/180));
var b=-Math.sin(angle * (Math.PI/180));
var c=document.getElementById("shiftx").value
var d=Math.sin(angle * (Math.PI/180));
var e=Math.cos(angle * (Math.PI/180));
var f=document.getElementById("shifty").value
var port=document.getElementById("display-input").value
document.getElementById("result").innerText="xrandr --output " + port + " --transform " + a.toPrecision(5) + ","+ b.toPrecision(5) + ","+ c + ","+ d.toPrecision(5) + ","+ e.toPrecision(5) + ","+ f +",0,0,1"
}
// el.addEventListener("change",function () {
// update_xrandr();
// }
document.querySelectorAll(".xrandr_calc").forEach(el => el.addEventListener("change", event => {update_xrandr()}))
document.querySelectorAll(".xrandr_calc").forEach(el => el.addEventListener("input", event => {update_xrandr()}))
document.querySelectorAll(".xrandr_calc").forEach(el => el.addEventListener("paste", event => {update_xrandr()}))
update_xrandr()
</script>
<p>Enjoy.</p>
<div class="blog-tags">
<a href="https://sprocketfox.io/xssfox/tags/monitor/">monitor</a
>&nbsp;
<a href="https://sprocketfox.io/xssfox/tags/xrandr/">xrandr</a
>&nbsp;
<a href="https://sprocketfox.io/xssfox/tags/display/">display</a
>&nbsp;
<a href="https://sprocketfox.io/xssfox/tags/rotate/">rotate</a
>&nbsp;
</div>
</article>
</div>
<footer>
<div>
<a href="https://github.com/xssfox" name="GitHub" aria-label="GitHub"
><em aria-hidden="true" class="fab fa-github-alt"></em
></a>
<a href="https://twitter.com/xssfox" name="Twitter" aria-label="Twitter"
><em aria-hidden="true" class="fab fa-twitter"></em
></a>
<a href="https://t.me/xssfox" name="Telegram" aria-label="Telegram"
><em aria-hidden="true" class="fab fa-telegram"></em
></a>
<a href="https://www.facebook.com/xssfox" name="Facebook" aria-label="Facebook"
><em aria-hidden="true" class="fab fa-facebook"></em
></a>
<a href="https://www.youtube.com/xssfox" name="YouTube" aria-label="YouTube"
><em aria-hidden="true" class="fab fa-youtube"></em
></a>
<div class="container">
<p class="credits copyright">
<a href="https://sprocketfox.io/xssfox/about">xssfox</a>
&nbsp;&copy;
2021
&nbsp;/&nbsp;
<a href="https://sprocketfox.io/xssfox/">xssfox</a>
&nbsp;&ndash;&nbsp;
<em class="fas fa-moon" id="dark-mode-toggle" aria-label="switch between dark and light mode"></em>
</p>
<p class="credits theme-by">
Powered By <a href="https://gohugo.io">Hugo</a>&nbsp;
Theme
<a href="https://github.com/matsuyoshi30/harbor">Harbor</a>
</p>
</div>
</footer>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment