Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Cross Oni Movement #1747

Merged
merged 21 commits into from
Mar 16, 2018
Merged

Cross Oni Movement #1747

merged 21 commits into from
Mar 16, 2018

Conversation

CrossR
Copy link
Member

@CrossR CrossR commented Mar 8, 2018

Potentially fixes #67.

I've not actually got 2 monitors, so I've written this such that it should work broadly moving across any Oni instances. Plus I don't think the screen number actually matters since I think if you have 2 1080p monitors, the top left of your primary is 0,0 and then the other ones are either -1920,0 or 1920,0, so this approach (ie using the current location) should work.

That said! I don't want to put a bunch of effort in based on vague assumptions I've had from reading StackExchange and GitHub issues, so if someone with 2 monitors could test it, that would be great. Currently, I've not bothered hooking up the movement keys, I'm just using the Ctrl+Shift+P menu to add Up, Down, Left, Right movements.

Assuming that works on multiple monitors, since it works for me on one at least:

  • Check issue with windows being correctly emptied, since currently if you close a Window, this stops working due to an object being destroyed.
  • Actually link this up up the to unhandled movement option.
  • Move the code out of main and into a separate file (+ tidy it)
  • Unit test it, and spend a little time seeing if CI tests are feasible.
  • Deal with minimised windows? Ie currently if you have 3 windows of oni, with the middle minimised, the middle will open up again.
  • Check the selection logic, and make sure it prioritises the smallest distance of the current movement.
  • Move logic out of OniEditor.

If not, well at least I only spent an hour or so on this to avoid other work.

Also check that there are valid windows to swap to, both initially and after filtering.
@bryphe
Copy link
Member

bryphe commented Mar 8, 2018

This is awesome, @CrossR ! Once we have this I might never need to leave Oni... I'll put browser and terminal in one window and code in the other haha

so if someone with 2 monitors could test it, that would be great.

Tested it out, worked perfectly moving right/left between my two monitors 👍

Unit test it, and spend a little time seeing if CI tests are feasible.

Thanks for thinking about the tests!

The CiTests may be tricky - we don't have any tests that launch multiple Oni instances today, and in automation, we don't force a single instance of the main process (so this actually wouldn't work, unless we made further changes to add a setting to allow that). I think a unit test for the window-switching logic would be sufficient, and we could document a manual test case here: https://github.com/onivim/oni/blob/master/test/Manual.md#manual-test-cases

It would be nice to have a full CiTest eventually, but I'm not sure it's the right tradeoff of value vs time at the moment (up to you though).

Other bullet points look great - excited to have this in!

@codecov
Copy link

codecov bot commented Mar 8, 2018

Codecov Report

Merging #1747 into master will increase coverage by 0.09%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1747      +/-   ##
==========================================
+ Coverage   42.37%   42.46%   +0.09%     
==========================================
  Files         163      165       +2     
  Lines        6252     6349      +97     
  Branches      881      889       +8     
==========================================
+ Hits         2649     2696      +47     
- Misses       3429     3477      +48     
- Partials      174      176       +2
Impacted Files Coverage Δ
...owser/src/Services/Learning/Achievements/index.tsx 33.33% <0%> (-6.67%) ⬇️
browser/src/Utility.ts 54.54% <0%> (-1.98%) ⬇️
...vices/Learning/Achievements/AchievementsManager.ts 78% <0%> (-1.6%) ⬇️
browser/src/neovim/NeovimAutoCommands.ts 5.71% <0%> (-0.35%) ⬇️
browser/src/neovim/NeovimInstance.ts 5.7% <0%> (-0.09%) ⬇️
browser/src/Store.ts 23.8% <0%> (ø)
...g/Achievements/AchievementNotificationRenderer.tsx 44.11% <0%> (ø)
browser/src/Editor/Editor.ts 72.72% <0%> (+0.85%) ⬆️
browser/src/neovim/NeovimBufferUpdateManager.ts 45.09% <0%> (+35.34%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6d9cd90...7aa6bc6. Read the comment docs.

Not sure if this should be the default or not.
Is possible we could hook up a config option and pass that over the IPC to here to make it configurable.
@CrossR
Copy link
Member Author

CrossR commented Mar 12, 2018

It looks like the error I get isn't due to the windows list not being correctly updated on close, but rather when the initial Oni window (that is, the first Oni window to be opened) is closed, the windows list gets deleted entirely.

Need to look into why that is happening, and how to fix it...

@CrossR
Copy link
Member Author

CrossR commented Mar 14, 2018

It seems that for some reason, when the main Window is closed, the first item in the windows array becomes unreferenced...for some reason. Which then causes issues since I need to check over all the values in that array. I'll poke around it for a bit tomorrow, since I've not had that much time today to check.

@bryphe
Copy link
Member

bryphe commented Mar 14, 2018

It seems that for some reason, when the main Window is closed, the first item in the windows array becomes unreferenced...for some reason.

Ah, interesting. I think I see one problem (it's really an existing bug, just easier to hit now with this change).

The repro I did was open two Oni instances:

  • Focus the second instance
  • Close the first instance
  • <C-w><C-h> to the boundary
  • Hit this exception:

image

It looks like the issue is this line here:

    mainWindow.on("closed", () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        windows = windows.filter(m => m !== mainWindow)
        mainWindow = null
    })

The problem is that, mainWindow always gets set to the newest editor. So when we create the second window, mainWindow now points to that second window. Then, when we close the first window, we filter out the second window, leaving the now-disposed first window.

A quick fix is to hold a reference to the current window in the closure:

const currentWindow =  mainWindow = new BrowserWindow({

And then use that in the filter:

    // Emitted when the window is closed.
    mainWindow.on("closed", () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        windows = windows.filter(m => m !== currentWindow)
    })

It might be good eventually to get rid of the mainWindow. There's nothing really special about the first window we create - it might be better to replace the places that use mainWindow with the currently focused window, or the first window in the windows array.

Added function to get current active window, and renamed main window to currentWindow.
I.e. always move to the closest window on the right.
@@ -84,7 +84,9 @@ ipcMain.on("move-to-next-oni-instance", (event, direction: string) => {
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let windows: BrowserWindow[] = []
let mainWindow: BrowserWindow = null
const activeWindow = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid! Thanks for fixing this 👍

@CrossR
Copy link
Member Author

CrossR commented Mar 14, 2018

I've added tests for all the easily testable parts. The remaining function that hasn't been tested doesn't return anything, so we'd need a CI test that can check the focus of a window, which sounds pretty awkward.

Only thing left here I think is I want to check is that where I've added the subscription makes sense in OniEditor?

Oh and the original ticket mentions adding commands for Expand Up/Down etc, but I think that is distinct enough to be done in a separate PR. Could probably also do with making the movement into an action that users can bind, such that a user can use it without having to move to the edge of the window with their own keybinds.


// Given a window, check if it is the best window seen so far.
// This is determined by the difference in X and Y relative to the current window.
export function checkWindowToFindBest(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool! Great set of unit tests covering this functionality.

"test:unit:browser": "npm run build:test:unit && cd browser && electron-mocha --renderer --require testHelpers.js --recursive ../lib_test/browser/test",
"test:unit": "npm run test:unit:browser && npm run test:unit:main",
"test:unit:browser": "npm run build:test:unit:browser && cd browser && electron-mocha --renderer --require testHelpers.js --recursive ../lib_test/browser/test",
"test:unit:main": "npm run build:test:unit:main && cd main && electron-mocha --renderer --recursive ../lib_test/main/test",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for setting this up! 💯

@@ -170,6 +171,10 @@ export class OniEditor implements IEditor {
buf => extensions.includes(path.extname(buf.filePath)),
buf => new ImageBufferLayer(buf),
)

windowManager.onUnhandledMove.subscribe((direction: string) => {
Copy link
Member

@bryphe bryphe Mar 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just saw your comment - there is one problem with the location here. In the 'multiplexing' scenario (when editor.split.mode is 'oni'), we will potentially have multiple OniEditor instances - so that means this would get fired multiple times.

One option would be to plop this code in browser/src/index.tsx, after we've created the WindowManager. Or add an activate method in MultiProcess, like we have for some of the other services, pass in the windowManager as a dependency, and wire up the event there.

@bryphe
Copy link
Member

bryphe commented Mar 15, 2018

I've added tests for all the easily testable parts.

Awesome! Thanks for wiring up unit tests for our main process - big step forward to have some of that code covered under test. This is a great example of a change that improves the quality of the code while implementing new functionality.

The remaining function that hasn't been tested doesn't return anything, so we'd need a CI test that can check the focus of a window, which sounds pretty awkward.

Agree 100% - I don't think a CiTest is necessary for this.

Only thing left here I think is I want to check is that where I've added the subscription makes sense in OniEditor?

Ah ya, good catch - there might be an issue in the 'multiplexing' case - I left a more detailed comment on the file. But we probably will want to move it to a place that only gets initialized once.

Oh and the original ticket mentions adding commands for Expand Up/Down etc, but I think that is distinct enough to be done in a separate PR. Could probably also do with making the movement into an action that users can bind, such that a user can use it without having to move to the edge of the window with their own keybinds.

Yep, makes sense to have that be a separate PR 👍

Nice work! 💯

@CrossR CrossR changed the title [WIP] Cross Oni Movement Cross Oni Movement Mar 15, 2018
@CrossR
Copy link
Member Author

CrossR commented Mar 15, 2018

Assuming no failures on the CI side of things, this should be done now.

@bryphe
Copy link
Member

bryphe commented Mar 15, 2018

Awesome! Code changes look great 👍 Approving now

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multi-monitor support
2 participants