> Its probably best to use the tmux terminology if you're talking getting > stuff out of tmux because that's what it'll use :-).
Having delved a bit deeper, window isn't quite the right term either as you can have multiple panes in one window. I would prefer to show each pane in its own tab (eventually I'll support panes that look like tmux's but we're not there yet). So please substitute Pane for Window in the API. > > Well, this stuff is actually fairly passive. > > There are two big problems: > > - Asynchronous events. What happens if the user closes a window, or > moves it to another session, or tmux resizes it? There are going to be a > lot of places where we need to trigger an event where at the moment we > just redraw our clients. If a user closes a window, then the ReadFromWindow() would return EOF, just like read(2) does. > - UI side channels that are currently per client not per session. What > about the status line or if the user tries to enter the command prompt? > I always regret making this stuff per client but it is there now. I'm not familiar enough with all the ins and outs of tmux to say, but my intuition is that we should not expose the command prompt or status line in this UI. As far as I can tell, the command prompt is used for UI tasks that would be taken over by my GUI. If it's necessary for the server to be able to push a status message to the client that would normally appear in the status bar, I'd say ReadFromPane (formerly ReadFromWindow) should support out-of-band signaling. In other words, it'd change to something like: typedef enum { RAW_DATA, // buffer will be filled in with output from tty STATUS_UPDATE // server is requesting that a message be displayed to the user } MessageType; int ReadFromPane(Pane*, int maxBytes, char* buffer, MessageType* messageType); We'd pop a dialog box when we get a status update (well, probably something less annoying than a dialog box, but you get the idea). > Also I guess you're content to let tmux manage panes. Please see my correction above - we would manage panes ourselves. >> // like select(2), but over Windows. Returns a vector of windows where >> ReadFromWindow() won't block. >> vector<Window*> GetWindowsWithNewInput(); > > Yeah but probably you'd be building the data yourself from stuff tmux > has fed on whatever event channel it has. Sorry, I don't follow. My thought was that tmux would package up output from windows into messages that would be sent over our framing protocol to the client, which would unpack them and determine which panes have new input. So suppose you have two panes open (either in one window or in two, it doesn't matter), call them pane0 and pane1. Suppose pane1 produces output "foo". Then output isomorphic to this would be sent to stdout by tmux: message { type: raw_data sender: pane0 value: foo } My client would read this off the wire and cause GetPanesWithNewInput() to return a vector containing only pane0. >> // Returns a single line of text from the nth line of scrollback for a >> given window. A ScreenCell is a struct with a character, foreground >> color, background color, etc., representing a single onscreen >> character. >> vector<ScreenCell> GetScrollbackHistoryInWindow(Window*, int lineNumber); > > What would be most likely is that you would request a line from the > history and tmux will give you a sequence you can feed into your parser > to draw it. Can you define "sequence"? VT100 escape codes are fine as long as any existing state if taken into account. So if line 0 has a code to change the foreground color and I request line 1, it must begin with the foreground color escape code. >> // Notify window of a size change >> void ResizeWindow(Window*, int width, int height); > > You could actually sort of do this already with force-width and > force-height options. Basically need to feed your data into the existing > maximum window size calculations (resize.c). This is a little messy given the window/pane feature that tmux has and iTerm2 doesn't. For now I'd probably prefer to do something really simple like move each pane into its own window when iTerm2 connects and then use the existing SIGWINCH functionality, so this API would be unnecessary. If two clients are attached to the same server, tmux does some presentation work (drawing a "no-man's land" of periods outside of the window in the second client). I think tmux would have to change its behavior in this mode to not draw those UI elements and just act like a window that refuses to resize. >> >> // Close a window >> void CloseWindow(Window*); >> >> >> Does this help clear up what I had in mind? > > I'm thinking the right way to do this would be to decouple the display > side of the client stuff a bit (where the client is the client object in > the server not the client process). At the moment there are basically a > few operations: > > - Exit (also detach). > - Lock. > - Here's an input command (draw line, etc etc). > - Get the tty size. > - Redraw everything including the status line. > - Redraw just the status line. > - Redraw a single pane. > - Redraw just the pane borders. > - Show pane identifiers for N time. > - Show message (on the status line) for N time. > - Clear message. > - Start prompt (on the status line). > - Clear prompt. > > So instead of this, we would start saying "the window has been split" or > "a window has been closed" or "this window has been resized" and it > could decide what it needed to redraw or whatever itself. > Once iTerm2 is attached, it wouldn't receive instructions to "redraw the screen" from tmux. You'd send us new output (whatever output you received wrapped in our protocol), but we'd handle presentation ourselves. It's possible that tmux's idea of what the screen looks like would get out of sync with iTerm2's, but those are minor edge cases (mostly having to do with rewrapping long lines when a window resizes) that I'm not too concerned about. > If you look for server_redraw_* in the code it is an idea of where this > would have to be changed. I'm going to be on a long plane flight tomorrow, and I plan to spend it reading tmux code. Hopefully I will come back from vacation able to speak intelligently about your internals :). > So what we would do for your idea would be then add a new client type > that instead of maintaining tty state and updating the tty, passed on > the event over some channel. > > This would allow you to take over the display part of the UI and leave > tmux doing everything else (key bindings, options, yadda yadda). I am hopeful that we can move all key bindings into iTerm2 so that tmux passes 100% of a user's keyboard input cleanly through. My least favorite part of terminal multiplexers in general is having to sacrifice a key combination. > When you want to manipulate or query tmux state I think you could use > existing tmux commands. It might be nicer to have a set of underlying > primitives that the commands were based on and that you could invoke but > that is probably quite a big job. The existing set of commands covers some nontrivial portion of what I need, so it seems obvious to me that the protocol we develop should be based on your existing commands and their syntax. I think it would be great if this became an established protocol that other terminal emulators coded to. If this works like I think it will, it could really change the way people interact with their terminals. ------------------------------------------------------------------------------ Centralized Desktop Delivery: Dell and VMware Reference Architecture Simplifying enterprise desktop deployment and management using Dell EqualLogic storage and VMware View: A highly scalable, end-to-end client virtualization framework. Read more! http://p.sf.net/sfu/dell-eql-dev2dev _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users