Cursor position to pixel position


I’m trying to get the pixel position for the cursor. I’ve got something like this:

editor = atom.workspace.getActiveTextEditor()
screenPos = editor.getCursorScreenPosition()
element = atom.views.getView(editor)
pixelPos = element.pixelPositionForScreenPosition(screenPos)

The value I get back has a top that’s way too high, and if I put an element there it ends up off screen below the editor.

I tried setting a breakpoint and checking other positions. For reference, lines 107 through about 140 are visible on screen. The cursor is on line 129, which is about halfway down my 1920x1080 screen and slightly more than halfway down the editor.

> editor.getCursorScreenPosition()
Point {row: 128, column: 21}

>element.pixelPositionForScreenPosition([128, 21])
Object {top: 2048, left: 176.796875

// the top visible line is number 107
// expect to be pretty close to 0...
>element.pixelPositionForScreenPosition([106, 0])
Object {top: 1696, left: 0}

Am I doing something wrong or is my understanding of TextEditorElement::pixelPositionForScreenPosition incorrect?

Thanks for any help!


The pixel position is in reference to the top of the file which will be bigger when you scroll down.

Edit: Everywhere in the API the screen position, pixels or rows, is from the top of the document not the visible pane. This can be confusing. Maybe they should have called it document positions.


That explains the behavior I’m seeing - thanks.

So if I want to show a “popup window” underneath the cursor, I need coordinates within the visible pane, right? How might I go about doing this?


It isn’t easy. Here is how I did it in markdown-scroll-sync.

Of course someone might come along and replace these 25 lines with a 2-line solution. (Please).


It just occurred to me that for this problem you can use simpler code than what I showed you. You just need to scan the lines and look for one that has the line number matching the line number of the cursor. Then steal the offset of that line to position your popup. The code to do this is a subset of the code I showed you.


What ended up working for me was to add a marker with editor.markBufferRange(), and then decorate it via editor.decorateMarker(). This takes care of the positioning for me.