Skip to content

Conversation

@arikorn
Copy link
Contributor

@arikorn arikorn commented Oct 21, 2025

This completes my proposal in Issue #2227 , as modified by Julian's requests...

  1. Steamdeck Plus LCD strip swipe actions
  • Horizontal swipe changes pages
  • Vertical swipe sends rotate actions
  • (Added a swipePage action to SurfaceHandler to handle the page change.)
  1. Add options to disable page-swipe and to restrict page access
  • Options are added to SurfaceGroupConfig
  • Modify EditPanel.tsx to add the new options
  • Modify SurfaceGroup.setCurrentPage to handle page restrictions
  • Import/Export new fields (page IDs are converted similarly to startup_page_id and last_page_id
  • (Modify InternalPageIdDropdown to allow multiple values)
  1. Update related documentation.

- Horizontal swipe changes pages
- Vertical swipe sends rotate actions
- (Added a swipe action to `SurfaceHandler` to handle the page change.)
- Options are added to `SurfaceGroupConfig`
- Modify *EditPanel.tsx* to add the new options
- Modify `SurfaceGroup.setCurrentPage` to handle page restrictions
- Import/Export new fields (pages are converted similarly to `startup_page_id` and `last_page_id`
- (Modify `InternalPageIdDropdown` to allow multiple values)
@thedist
Copy link
Member

thedist commented Oct 21, 2025

Horizontal swipe changes pages
Vertical swipe sends rotate actions

Just thinking about future growth here, would it not be better for touchscreen inputs to have their own full set of gestures that can be linked to actions, rather than trying to shoehorn them in to existing functionality?

For example, the SD+ LCD may just have swipe up, down, left, and right, but what if future touchscreen inputs we also want to include gestures such as rotating, or other such things?

Would it not make more sense to build it out properly now, rather than take a shortcut to rig it force horizontal swipe to do page changes, and vertical for rotation actions, which could be fine for some users but not everyone wants to have an LCD screen have to span multiple Companion pages for different functionality

@Julusian
Copy link
Member

My take is that the api of this should be made a little more generic, so that the terminology 'swipe' remains inside the elgato device implementation. I can imagine other surfaces where they have buttons which make sense to be dedicated page up and down (I feel like there was a request for this from a satellite user at one point).
And this PR could prepare for that by limiting where the 'swipe' terminology is used.

That would also mean that this is not a start for any more generic touch interactions, as the touch becomes an implementation detail of the elgato surfaces.
In the future when we have more generic swipe support, then the elgato surfaces can be updated to use that instead of this fixed behaviour

This helps setups where you need to be able to swap out a Stream Deck quickly, and also need actions to reference specific Stream Decks.
You can create your groups and program the system ahead of time, then later add or remove surfaces to the groups without needing to update any buttons.

## Use Case 3: Establishing "Permission Groups" with restricted access
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this is a separate use case for groups.

From my reading of the implementation, the page restriction is possible for 'standalone' surfaces too.
And from reading this, it sounds like I should be able to add multiple surfaces to a group to limit them to a set of pages, but have each of them on separate pages; which is not the case.

I think this bit about restricted access should maybe be its own page in the docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, I compromised, adding "when it applies" comments and also adding a new page. Feel free to modify as you see fit.

Also, because "security" settings are scattered in the UI, I added a help page with links to them all...

@arikorn
Copy link
Contributor Author

arikorn commented Oct 21, 2025

Thanks @Julusian & @thedist. I'm short on time, right now but perhaps you could help with the following?

Something in the WebUI code/config changed recently and is causing my WSL to crash when running yarn dist:webui -- this is a full system crash of WSL. Since switching to whatever was current before I submitted this PR, it has crashed 2/3 times and really seemed to be struggling (i.e. very slow) on the one that made it. Do you have any guesses what could be causing it? I suspect that it's just using way more memory than before... Any help would be most appreciated!!!

@arikorn
Copy link
Contributor Author

arikorn commented Oct 22, 2025

Well, a bit of sleuthing identifies the monaco library as the culprit for my crashing. This appears to be one of the known cases for the longstanding Vite "memory leak" issue.

To be precise when running yarn dist:webui on:
commit 5135aca - it uses 4GB of memory
commit 30bc902 (the next commit) - needs 8+GB of memory. Monaco itself is only 150 MB or so.

My temporary workaround is to allow WSL to use more than 50% of system RAM (yes, I don't have "enough" RAM, but it has worked fine until now). But it's very frustrating that relatively small changes cause such huge jumps in memory usage.

Have you considered moving away from Vite? For example, the React folks themselves recommend Next.js and go so far as saying that it is the closest thing to "the React team’s full-stack architecture vision" I know nothing about Next.js but this is the second time a small change has blown up Vite's memory consumption (during build). And the issue itself is several years old, with the developers apparently saying that they're not going to/can't fix it (last comment there).
Perhaps another workaround in that discussion might work here? (disable sourcemaps or manual chunking?) Thoughts? Comments?

@Julusian
Copy link
Member

Have you considered moving away from Vite? For example, the React folks themselves recommend Next.js and go so far as saying that it is the closest thing to "the React team’s full-stack architecture vision" I know nothing about Next.js but

I am not sure if any of those frameworks are going to be a good fit, as we are a slightly unconventional app. Companion has a lot of state loaded upon connection with continual syncing (very much a SPA), and while next can technically maybe handle that it wants to be building a more traditional webapp.
So I would expect quite a bit of fighting to get things to play along.
And I had another project recently where I was tasked to port from next to vite as next was too slow and memory hungry in dev, so at least that one may end up no better


I suspect that some kind of forced chunking or maybe even not bundling monaco during dev would be the way to go (monaco tries to load from a cdn, so it should be pretty trivial to let it do that during dev)

@arikorn
Copy link
Contributor Author

arikorn commented Oct 23, 2025

Thanks Julian, a fix to the memory issues would be awesome. (I started reading rollup documentation but it seems like going down a rabbit hole, which at least at present I'm trying to avoid...)
For now, I've figured out the "best" WSL settings to avoid a crash: leave "memory size" alone, but increase swap size, which is set very low by default. In the end, I suspect there's no effective difference between these two parameters, because if I allocate more RAM, it just means that Windows has to swap something else into its swap file... and WSL seems reasonably well-behaved in that it only grabs what it's actually using at any given time. Whether I increase "memory size" or "swap size" in WSL, yarn dist:webui now takes 3x longer than it used to (2.5 minutes vs. 45 seconds).

Ok. Now back to this PR... (Should I copy this part of the conversation out into a new issue?)

@arikorn
Copy link
Contributor Author

arikorn commented Oct 23, 2025

Before I go changing code, (well OK, I actually started, which led to the following thorughts) there may be a slight mismatch in our "visions". On the one hand I like the idea of tucking "swipe page" in with the Elgato surface implementation, especially regarding the config options, but on the other hand, I don't agree that adding a "page swipe" event is a "slippery slope", since its purpose is really quite different (these numbers do not correspond to your comment numbers, above, Julian):

  1. I would argue that, "page swipe" really is a special case since, by design, it is not bound to a particular button or page. Well, I suppose the StreamDeck Neo has dedicated page buttons but I suspect your treating them as regular buttons, so it doesn't count? The real issue, of course, is not whether we call it "swipe" or "change" but where the constraining code belongs:

  2. Most importantly, my understanding of the need for "enable swipe to change pages" was a security issue: some people don't want their users to swipe off a particular page and even though this PR allows limiting page access explicitly, some people may "just not want it enabled, @#$!*". In this case it makes more sense to keep the code to enable/disable page swipes in SurfaceHandler, so that we don't have to manually enforce this restriction on each surface that wants to implement a page change event. (Incidentally, I solicited feedback on FB and several people "really wanted it" on their Loupedecks. I pointed out your recent additions in that regard, but one could certainly imagine linking one of the bars to page swipe...).

  3. Not so sure I agree that adding a "page change" event here somehow limits future designs. I would say, if anything, it provides a hook that will allow you to fix it in one place instead of in each surface's implementation.

  4. Separately, Julian wrote:

    from reading this, it sounds like I should be able to add multiple surfaces to a group to limit them to a set of pages, but have each of them on separate pages; which is not the case.

    I was assuming that each user would have their own controller (like an RPi + Surface for each location/user, or maybe Satellite, if it can act independently in this way?), so they would not be forced to be on the same page. So in this case, including their devices in a group it will make it much easier to maintain the permissions and/or hot-swap surfaces. It is because of this scenario that I make the permissions available as a groups property (and also why I put it in the groups.md page, though I agree that it applies to ungrouped surfaces as well). I have no personal experience with multiuser setups, so if my assumption is wrong here, I'm happy to remove it from groups. And, to be fair, I'm not sure that you're recommending removing page limits from groups but I think you are recommending removing enable page swipe from groups, whereas I see them as all of a piece.

@dnmeid
Copy link
Member

dnmeid commented Oct 24, 2025

Just thinking about future growth here, would it not be better for touchscreen inputs to have their own full set of gestures that can be linked to actions, rather than trying to shoehorn them in to existing functionality?

I sencond that concern.
At the moment Companion is not really suited for anything else than button push and release. Even the rotary actions are not the most elegant solution. But for a swipe integration I think the best bet we have currently is to misuse the rotary actions.
In the current situation a left/right swipe could trigger rotation left right on the first LCD button and up/down swipe could trigger rotation on the second LCD button.
I've done this with the swipe gesture on the Mirabox N3 but with the slight advantage that there are only four Touch strip buttons but five LCD buttons, so I had an empty button to map to.

But I think mapping to rotary actions in the third row of that surface would be perfectly fine and doesn't do any harm for now.
There may be a break in the future when we maybe introduce gestures or x/y touch but I'd say the impact may not be huge.

I would not introduce new configuration or a new page change logic where the surface manages it's own page. I'd prefer everything of this being handled by existing set surface page actions, so the button will invoke a page change and there is no need to add any new surface methods. I think this will be a dead end street and much more complicated to upgrade later.

@dnmeid
Copy link
Member

dnmeid commented Oct 24, 2025

I would argue that, "page swipe" really is a special case since, by design, it is not bound to a particular button or page.

I don't follow that. I think you are not thinking open enough. Just because Elgato uses the swipe gesture for page change doesn't mean a Companion user wants that too.
The hardware offers swipe on the LCD-strip, so it makes sense to make this available on one of the buttons on the LCD strip. For me that doesn't need to pe a page change.
The goal of Companion is to give the users the power to do what they want. If they want to use swipe to turn up down volume, they should be able. If they want to use the Neo page buttons to start a movie, they should be able.
We support some surfaces with hardware labeled buttons, but we just offer them as a universal Companion button, no matter what the manufacturer thought people should do with them.

@arikorn
Copy link
Contributor Author

arikorn commented Oct 25, 2025

Thanks for the feedback @dnmeid
(It took me a long time to figure out your first comment because I am not familiar with the Mirabox line and the N3 looked nothing like you were describing. Eventually I stumbled across the N4, and now your comment makes sense, and hopefully, so will my response!)

It sounds like we all agree that Julian's recommended code changes address any future-proofing, and I've decided to accept his code advice, so no need to comment further on that.

Let me clarify some details that may help with our discussion:

  1. This PR implements button-specific swipe actions for all buttons in the LCD-strip by mapping vertical swipe gestures to rotational actions. The change-page action is independent of that functionality. By the same token, there's no "room" to map a horizontal swipe to any of the LCD-strip buttons, since they already all have their own rotational actions in this PR.
  2. The SD+ API/firmware has limitations which, in particular, do not make it reliable for button-specific horizontal-swipe actions (details below).
  3. The beauty of a surface-driven page-change functionality, and the reason Julian and I think it would be a good addition to Companion, is that it is independent of pages and (in the case of SD+) independent of buttons. As one commenter on Issue Support swipes from Streamdeck plus #2227, correctly noted: "page +/- would free up 2 buttons"...and that's 2 buttons per page! This is part of the allure of mapping page swipe to changing pages: it is simple and it frees up space. Conversely, forcing everyone to add page-change actions to some "hidden" button on each page (not to mention needing them to enable rotary actions to do so) would be clumsy, confusing and error-prone compared to having a non-button page-change action that just works as you expect it to. Put yet another way, while we shouldn't be bound by what the manufacturer does, sometimes they do have good ideas 😀.

So given that information, is the user really losing anything by not having full flexibility on horizontal swipes? This PR already gives them four new rotational buttons, and to reiterate: I'd say that insisting that the swipe maps to some "hidden" location on each page, would be a disservice to the vast majority of users. A simple compromise is to allow mapping to a button if "swipe to change page" is turned off. I'm not strongly opposed to this, though I do question its value considering the SD+ API/firmware limitations discussed next. To a large extent, I suspect that doing so would just open up the advanced user to frustration with the "feature".

Here's what I found to be the Stream Deck+ swipe capabilities and limitations:

  • The SD+ API provides no interactive feedback, i.e. you get a single swipe event at the end of the swipe, no "swiping" or anything else while the finger is on the LCD strip.
  • The API provides start and end coordinates, but these coordinate are only qualitative, i.e. the direction is correct but the start and end coordinates are generally not accurate.
  • As such, the SD+ API can be trusted for "user swiped left/right" (or up/down), but not for anything quantitative, such as setting a slider or shuttle.
  • To make matters worse, even for short horizontal swipes, I did not find it reliable enough to assign the action to a specific button
    A bit of additional detail may be found in my final comments to Issue Support swipes from Streamdeck plus #2227.

Since the swipe is not quantitative, a user trying to map horizontal swipes to an incremental change (i.e. rotational actions) would quickly become frustrated with the having to swipe horizontally over and over again to get a desired change. So, again, while not opposed to allowing it, I question whether it's a good idea.

In terms of what users want: let's not forget that this PR is addressing is a three year old issue, so there is clearly a longstanding desire for a solution. In fact, I recently posted a short video on FB demonstrating what this PR does and soliciting feedback: it got a large and overwhelmingly positive response, so I think it's safe to say that Companion users are eager to have the functionality added by this PR. (In fact the only "complaints" in the comments were that they want the same thing for their favorite surface 😀.)

@Julusian
Copy link
Member

In this case it makes more sense to keep the code to enable/disable page swipes in SurfaceHandler, so that we don't have to manually enforce this restriction on each surface that wants to implement a page change event

Maybe, but I see this PR as being 2 features; one for restricting page changes in general, the other specifically about the swipes on the sd+.
The swipes on the sd+, is something that will appeal to a group of users, likely largely those who are used to/expect this interaction becuase of its presence in the elgato software. Not everyone will want that.

I'm not opposed to this being something more generic. Perhaps the best approach is to a proeprty on the SurfacePanelInfo interface to say supportsPageChanges (or other wording), which will be used to enable the ui field, and can be used by SurfaceHandler to first check if the pageChange events should be ignored completely.

I was about to say that at it is just the one surface using it, then it might not be worth that effort. Then realised that in order for this to work from satellite (and the surface api rework), it probably does need to become a property like that.


so they would not be forced to be on the same page

The whole job of surface groups is to link surfaces to be always on the same page.

And, to be fair, I'm not sure that you're recommending removing page limits from groups

No, I am not suggesting this.
As it is the group which decides what page each surface inside the group is on. Which is why that once a surface is added to a group, its 'home page' & 'current page' properties disappear, as they are now defined by the group.
(Technically, those properties always belong to a group, but an ungrouped surface has an auto-generated group to keep things consistent internally)


I would not introduce new configuration or a new page change logic where the surface manages it's own page. I'd prefer everything of this being handled by existing set surface page actions, so the button will invoke a page change and there is no need to add any new surface methods.

On a technical level I kind of agree, but on a UX level having to manually setup 8 actions per page to get the same page change behaviour is not going to be nice.
I think that having the option to enable this swipe to change page is a nice UX improvement, and has a very small maintenance cost.
Ignoring the bits about restricting the pages (which I think is also nicer UX and a separate feature), then it becomes maybe 50 lines to do the pageChange stuff, including the stream deck implementation.

And yeah, maybe we will redo it later, I dont see a problem with having this until we have something better. Of course, that is if we can even map the lcd on this into something better, seeing as how limited the events are

I am wondering if when this page swipe stuff is disabled, perhaps left and right swipes should trigger the same rotation events on the lcd strip buttons.
While splitting it out might be better, I think that hiding it on the buttons above will make it very hidden..

- ensure as best as possible that page restrictions are enforced (a) at startup and (b) even if enabled after visiting now-restricted pages.
* Ensure all `configFields` properties are added to to panelConfig
* Ensure that defaults specified in `configFields` are honored
* Ensure that missing fields are added when importing a preexisting export.
* Deal with TypeScript oddities
@arikorn
Copy link
Contributor Author

arikorn commented Oct 26, 2025

These are more changes than I had anticipated, so I broke it up into separate commits to make it a bit "modular"

  1. Fix my original code for restricting pages, which was inconsistently applied. I think it's properly covered now, so if page restrictions are in place it is difficult-to-impossible to go to a restricted page. The only exception is "current page" while the person is editing, because it could mess with things while they're updating the list...(i.e. the current page may be the next item the user adds, so I don't want to change pages just because it isn't there yet...) And since I can't tell when they're done, it stays unchanged.
  2. Move the "swipe" wording and functionality to the Elagato class. This is straightforward, but affects a bunch of files.
  3. In doing so, I ran into some rather confusing and/or buggy behavior in how Companion treated the new custom config field - both in a completely clean database and when dealing with imports. This took way more effort to find and fix than anticipated, but hopefully it's done now for all future cases. Basically, Companion now reads the configFields property (output of the getConfigFields() you pointed out) and makes sure they're all included in the new config object and that defaults are copied from the configFields if present. (This also avoids the need for the essentially-redundant panel.getDefaultConfig() method.)
  4. Finally, I updated the documentation.

This should address all comments prior to your new comment today, Julian, but doesn't address, yet, your new idea, which I either need time to digest or more clarity on how you see it used. On that note:

  • Would the Surface change the value of supportsPageChanges depending on the user config (so perhaps, something to the effect of currentlyAllowingPageChanges)? or is it a "capabilities" statement, and then the config info would be moved back out of ElagatoStreamDeck.ts? (I'm guessing the former or neither...)
  • I'm interpreting your final comment to indicate that horizontal swipe should not be mapped to an arbitrary button if swipe-to-change-page is disabled. To be more specific, this PR does not include an option to disable swiping in general because if a person doesn't want to use the vertical swipes, they can just skip or disable rotary actions, same as any other button, so swipe-to-change-page only affects horizontal swipe, which I'm claiming for now, cannot be reliably assigned to buttons.

Thanks again for all your advice, input and encouragement!

This branch is now strictly focused on SD+ swipe actions
@dnmeid
Copy link
Member

dnmeid commented Oct 29, 2025

Ari said:

  1. The beauty of a surface-driven page-change functionality, and the reason Julian and I think it would be a good addition to Companion, is that it is independent of pages and (in the case of SD+) independent of buttons. As one commenter on Issue Support swipes from Streamdeck plus #2227, correctly noted: "page +/- would free up 2 buttons"...and that's 2 buttons per page! This is part of the allure of mapping page swipe to changing pages: it is simple and it frees up space. Conversely, forcing everyone to add page-change actions to some "hidden" button on each page (not to mention needing them to enable rotary actions to do so) would be clumsy, confusing and error-prone compared to having a non-button page-change action that just works as you expect it to. Put yet another way, while we shouldn't be bound by what the manufacturer does, sometimes they do have good ideas 😀.

I absolutely don't follow that argumentation.
The thing that frees up two buttons is not a new independent mechanism of page changes. The thing that frees up the buttons is having the ability of processing swipes in any way. It doesn't matter how this is implemented if you want to replace page up/down buttons.

Forcing everybody to add some actions to a "hidden" button is not as bad as you are trying to make us believe. I follow you with it being easier to have a page change functionality built into the surface like you propose for exactly that one purpose: mapping page changes to the horizontal swipe. But as I said, that is not the Companion way of doing things. This would be a paradigm shift and introduce a new interaction style in Companion that is currently not there. As I see it there will definitely be some users that want to do exactly that, triggering page changes from swipe, but there will also be users that want to do something else with horizontal swipe. You didn't address that concern.

Julian said:

On a technical level I kind of agree, but on a UX level having to manually setup 8 actions per page to get the same page change behaviour is not going to be nice.

Why 8 actions? Isn't it the same two actions like you have to set up on every other surface when using regular buttons?
What I can think of, is making the default destination for page change actions a property of the surface, so when a user wipes the page or initial setup is done, we don't always use the top left three buttons but are more clever in placing default page change buttons.
EDIT: forget about more clever page button position. I just realised how that would contradict my whole point here where all controls are placed on the grid and that is reusable with all different surfaces. I guess we have to consider the page button placment as a left over from the early days.

I think that having the option to enable this swipe to change page is a nice UX improvement, and has a very small maintenance cost.

I have a different assesment of the maintenance cost. I'm greatly remembered with this feature at the introduction of pin code locks. By that time we had exactly the same discussion. Someone had a working PR for introducing pin codes like we have now. I voted against the implementation as completely independent drawn buttons and input logic. Still today we are fighting with the quirks of this implementation because now there are completely different surfaces and users always want more functionality like individual lock-outs and individual landing pages and so on. Everything would have been straight-forward and easy to understand with an action-based lockout. And today many users do this anyway and use the dataentry module for it.
This change is going in the same direction. Now you think it is more easy and convenient. But Companion is not about convenience in first place. It is about flexibility, about making stuff possible. We hope to make this as accessible as possible and for that purpose I prefer to have consistency and the same solutions everywhere.
We now have quite a few surfaces that are doing some mapping of functionality to some places that you just have to know and can't easily see. That is the downside of the regular grid. I'm well aware of the grid pros and contras and still are convinced that the grid is the better solution. So now that we have that grid every physical control should only interact thru that mechanism.
In the same aspect I'm not the biggest fan of the X-Keys T-Bar variable or the surface variables e.g. for the RFID reader of SDS.
As I see it these variables are an intermediate solution that should be replaced in the future with a better soution.
Same is true for rotary actions, even if they are well established now, they can't be the final solution.

If we now introduce page control from the surface without using some element that lives on the grid and is configurable with our standard methods and at the place where it really happens (or at least close), that would completely not be inline with the Companion style again and would be hard to remove in the future.

For me that feels 100% like the same mistake we see over and over again from module developers. It is an implementation of exactly one workflow exactly the way the developer would use it. That is the reason why we have so many checkboxes and options only used by a few people.
You have to remember that we build a tool for building a tool to control something.

So ultimately we agreed on discussing such feature additions with the board before adding and that is what we should do.
I want to apologize for being very late to the party and hope Ari, you are not too mad if there is now potentionally work going to waste. Unfortunately spring and fall are my busy seasons and I can't be around every day.
Thank you anyway for your effort and I hope we can add the functionality one way or the other.

@arikorn
Copy link
Contributor Author

arikorn commented Oct 29, 2025

Not mad, @dnmeid: you have valid concerns and they should be addressed. Let me suggest that we already agree much more than we disagree and that there's a simple solution. In fact, I was going to start with a long list of "precedent" arguments, but you've already covered them! I understand that you don't like those precedents, but considering that you yourself have used them and even recommended them in your first comment, it's hardly cause for invoking a "nuclear option"!

If I understand you correctly, your main concern is that (a) people should have the option to do something other than page change for horizontal swipe and (b) that it should be mapped to the button grid.

Just to review what I believe we can agree on:

  • The request to support "swipes" from SD+ is three years old and...
  • The desire for swipe input for SD+ is still very popular, as witnessed by the overwhelming positive response on FB last week.
  • This PR maps vertical swipe actions to rotation actions for each button on the LCD strip.
  • The SD+ itself is somewhat limited in what else it can do. In particular, there is no support for interactive or "extent" gestures (i.e. where you can act based on the length or start/end positions of the swipe), nor do I find horizontal swipe reliable for dividing it into the four buttons contained in it.
  • There is plenty of precedent in Companion for surface actions that are not assigned to grid buttons (as you have enumerated above).

So what this PR does uncontroversially is: LCD strip swipes fully mapped to a grid and 100% consistent with current practices. The question is then what to do with the "bonus" horizontal swipe, since the grid is currently fully mapped.
Before answering let's consider the users' needs. More things we can agree on:

  • I believe we all agree that the overwhelming majority of users would want horizontal swipe to do page change.
  • I would also argue that anyone who wants to do something else with horizontal swipe is an advanced user and will therefore not mind having to jump through an extra hoop.

Put another way, the advanced user will have to jump through extra hoops regardless, the question therefore is: Do we force everyone to jump through hoops just because a small minority will want to?

So the simple solution is to tie the horizontal swipe to a first- or second-row button if "Swipe to Change Page" is disabled. This way, the advanced user has to do exactly the same amount of work as they would have had to do anyway, whereas the typical user gets what they want without frustration. (And considering the established precedents you have mentioned, without compromising the integrity of Companion's core tenets.). A somewhat more difficult/awkward solution would be to expand the SD+ grid to allow assigning horizontal swipe to a new button for the advanced users. (But of course that's a rather disruptive change relative to its benefit.)

Dorian wrote:

The thing that frees up two buttons is not a new independent mechanism of page changes. The thing that frees up the buttons is having the ability of processing swipes in any way. It doesn't matter how this is implemented if you want to replace page up/down buttons.

This is an important point, so worth elaborating on specifically.

  • Conventionally, one needs two buttons per page to do page up and page down.
  • If a user maps one of the vertical swipes to page up/down, it would take one button per page.
  • If we map horizontal swipe to a button in the first two rows, technically no buttons are consumed, but in fact the page-change action would still need to be put on every page, and since it's hidden in a rotary action of a "non-rotary" button, either that button has to be dedicated to page changes or it would be very awkward and confusing, since the user wouldn't be able to copy and paste to the next page without interfering with the button's "main" function.
  • Expanding the existing grid solves part of the problem but still requires adding a button to every page.
  • OTOH, mapping the "bonus" horizontal swipe to a changePage event, as implemented here, uses zero buttons and zero effort to put it on every page. To a large extent it's not unlike Companion's current behavior of automatically adding three page-change buttons to every page, only much more efficient.

To rephrase that last point: Companion clearly recognizes that page-changing is a special case/universal need. This PR follows in that tradition.

So the thing that frees up the most buttons and is the least frustrating for users is enabled by the new independent mechanism of page changes. And again, there is plenty of precedent for surface actions that work without using the button grid. So I still believe that it would be a great disservice to the majority of users to skip this functionality and as I've pointed out above, it can be done without imposing any restrictions on the few who will want to map it to a specific button.

I certainly welcome any alternative suggestions you might have for how to make things simple for the majority of users without restricting advanced users -- or indicating your preference of the two alternatives I suggested here for accommodating advanced users.

@arikorn
Copy link
Contributor Author

arikorn commented Oct 29, 2025

There's nothing like hitting the "send" button to provide extra insight 😀, but this one is probably worth its own space anyway:

It worth noting that the TCP/UDP API has predefined commands for Page Set and Page-Up/Page-Down that is independent of button-presses or the button grid, so that is yet another precedent for adding the same functionality to the surfaces API.

@Julusian
Copy link
Member

Why 8 actions? Isn't it the same two actions like you have to set up on every other surface when using regular buttons?

Yeah, but to replicate what this PR does (assuming the general rotation parts are merged), it requires adding a rotate left and a rotate right action to each of the 4 buttons that the lcd strip will translate to. As explained in this comment, that is going to be really tedious and manual to do:

but in fact the page-change action would still need to be put on every page, and since it's hidden in a rotary action of a "non-rotary" button, either that button has to be dedicated to page changes or it would be very awkward and confusing, since the user wouldn't be able to copy and paste to the next page without interfering with the button's "main" function.

Now you think it is more easy and convenient. But Companion is not about convenience in first place. It is about flexibility, about making stuff possible.

Yes and no. There are many things we do for convenience (often phrased as UX), that add complexity. I could argue that presets are exactly the same, as being purely convenience focused.
But for this feature, it is currently shaped as an opt-in thing (I need to verify that, but thats how I want it to be) which unlocks some advertised functionality of the device which some users are expecting.

As I see it these variables are an intermediate solution that should be replaced in the future with a better soution.
Same is true for rotary actions, even if they are well established now, they can't be the final solution.

Sure, but we are no closer to a better solution now than we were 3 years ago when rotary actions were first added.

So maybe this swipe stuff isn't the ultimate and final solution, but it will do until there is a plan and some momentum on a bigger solution.

If we now introduce page control from the surface without using some element that lives on the grid and is configurable with our standard methods and at the place where it really happens (or at least close), that would completely not be inline with the Companion style again and would be hard to remove in the future.

I cant say if I agree or disagree with this tbh. I don't have any ideas on how this could translate onto the grid in a nice way. Because to me this means being able to have some lcd interactions being done as if it were 1 control, and some interactions as if it were 4, and I cant see how to make that work in a sensible way that isnt either really space inefficient, a confusing layout or horribly complicated

Or we could do as we did recently for the old xkeys layout and simply remove them. I havent yet seen anyone complain/notice that we did that.

So ultimately we agreed on discussing such feature additions with the board before adding and that is what we should do.

No objection from me on doing that. With various people having been rather quiet recently I havent felt it worth trying to arrange anything on this.


I believe we all agree that the overwhelming majority of users would want horizontal swipe to do page change.

I wouldnt agree on 'overwhelming majority', but would say that some users of the sd+ would. That is enough to justify its value for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants