mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
terminal session: propagate resize events
The new 'Terminal_session::size_changed_sigh' RPC function registers a signal handler that is triggered each time when the terminal size changes. It enables the client to adjust itself to the new size by subsequently calling the 'size' RPC function. Of all terminal servers, only the graphical terminal triggers this signal.
This commit is contained in:
parent
96a068f90a
commit
8aa1e349fc
@ -252,18 +252,20 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
_driver(driver)
|
||||
{ }
|
||||
|
||||
void read_avail_sigh(Signal_context_capability sigh)
|
||||
void read_avail_sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
_driver.read_avail_sigh(sigh);
|
||||
}
|
||||
|
||||
void connected_sigh(Signal_context_capability sigh)
|
||||
void connected_sigh(Signal_context_capability sigh) override
|
||||
{
|
||||
_driver.connected_sigh(sigh);
|
||||
}
|
||||
|
||||
Size size() { return Size(0, 0); }
|
||||
bool avail() { return _driver.avail(); }
|
||||
void size_changed_sigh(Signal_context_capability) override { }
|
||||
|
||||
Size size() override { return Size(0, 0); }
|
||||
bool avail() override { return _driver.avail(); }
|
||||
|
||||
size_t _read(size_t dst_len)
|
||||
{
|
||||
@ -289,8 +291,8 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
|
||||
Dataspace_capability _dataspace() { return _io_buffer.cap(); }
|
||||
|
||||
size_t read(void *buf, size_t) { return 0; }
|
||||
size_t write(void const *buf, size_t) { return 0; }
|
||||
size_t read(void *buf, size_t) override { return 0; }
|
||||
size_t write(void const *buf, size_t) override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -104,9 +104,9 @@ class Open_file
|
||||
Genode::Signal_transmitter(_read_avail_sigh).submit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the file was successfully openend
|
||||
*/
|
||||
/**
|
||||
* Return true if the file was successfully openend
|
||||
*/
|
||||
bool file_opened() const { return _fd != -1; }
|
||||
|
||||
/**
|
||||
@ -167,9 +167,9 @@ namespace Terminal {
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() { return Size(0, 0); }
|
||||
Size size() override { return Size(0, 0); }
|
||||
|
||||
bool avail()
|
||||
bool avail() override
|
||||
{
|
||||
return !read_buffer_empty();
|
||||
}
|
||||
@ -209,18 +209,20 @@ namespace Terminal {
|
||||
return _io_buffer.cap();
|
||||
}
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh)
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
Open_file::read_avail_sigh(sigh);
|
||||
}
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability sigh)
|
||||
void connected_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
Open_file::connected_sigh(sigh);
|
||||
}
|
||||
|
||||
Genode::size_t read(void *buf, Genode::size_t) { return 0; }
|
||||
Genode::size_t write(void const *buf, Genode::size_t) { return 0; }
|
||||
void size_changed_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
Genode::size_t read(void *buf, Genode::size_t) override { return 0; }
|
||||
Genode::size_t write(void const *buf, Genode::size_t) override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -437,9 +437,9 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() { return Size(0, 0); }
|
||||
Size size() override { return Size(0, 0); }
|
||||
|
||||
bool avail()
|
||||
bool avail() override
|
||||
{
|
||||
bool ret = false;
|
||||
Libc::with_libc([&] () { ret = !read_buffer_empty(); });
|
||||
@ -490,18 +490,20 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
|
||||
return _io_buffer.cap();
|
||||
}
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh)
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
Open_socket::read_avail_sigh(sigh);
|
||||
}
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability sigh)
|
||||
void connected_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
Open_socket::connected_sigh(sigh);
|
||||
}
|
||||
|
||||
Genode::size_t read(void *buf, Genode::size_t) { return 0; }
|
||||
Genode::size_t write(void const *buf, Genode::size_t) { return 0; }
|
||||
void size_changed_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
Genode::size_t read(void *buf, Genode::size_t) override { return 0; }
|
||||
Genode::size_t write(void const *buf, Genode::size_t) override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -124,7 +124,7 @@ struct Terminal::Main : Character_consumer
|
||||
Read_buffer _read_buffer { };
|
||||
|
||||
/* create root interface for service */
|
||||
Root_component _root { _env, _heap, _read_buffer, *this, _terminal_size };
|
||||
Root_component _root { _env, _heap, _read_buffer, *this };
|
||||
|
||||
/*
|
||||
* builtin keyboard-layout handling
|
||||
@ -152,6 +152,7 @@ struct Terminal::Main : Character_consumer
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_handle_config();
|
||||
_config.sigh(_config_handler);
|
||||
|
||||
_input.sigh(_input_handler);
|
||||
|
||||
@ -198,13 +199,12 @@ void Terminal::Main::_handle_config()
|
||||
/*
|
||||
* Adapt terminal to framebuffer mode changes
|
||||
*/
|
||||
if (_framebuffer.mode_changed() || !_text_screen_surface.constructed()) {
|
||||
_framebuffer.switch_to_new_mode();
|
||||
_text_screen_surface.construct(_heap, *_font_family,
|
||||
_color_palette, _framebuffer);
|
||||
_terminal_size = _text_screen_surface->size();
|
||||
_schedule_flush();
|
||||
}
|
||||
_framebuffer.switch_to_new_mode();
|
||||
_text_screen_surface.construct(_heap, *_font_family,
|
||||
_color_palette, _framebuffer);
|
||||
_terminal_size = _text_screen_surface->size();
|
||||
_root.notify_resized(_terminal_size);
|
||||
_schedule_flush();
|
||||
|
||||
/*
|
||||
* Read keyboard layout from config file
|
||||
|
@ -31,10 +31,12 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
{
|
||||
private:
|
||||
|
||||
Read_buffer &_read_buffer;
|
||||
Character_consumer &_character_consumer;
|
||||
Size const &_terminal_size;
|
||||
Attached_ram_dataspace _io_buffer;
|
||||
Read_buffer &_read_buffer;
|
||||
Character_consumer &_character_consumer;
|
||||
Size _terminal_size { };
|
||||
Size _reported_terminal_size { };
|
||||
Attached_ram_dataspace _io_buffer;
|
||||
Signal_context_capability _size_changed_sigh { };
|
||||
|
||||
Terminal::Position _last_cursor_pos { };
|
||||
|
||||
@ -46,21 +48,36 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
Session_component(Env &env,
|
||||
Read_buffer &read_buffer,
|
||||
Character_consumer &character_consumer,
|
||||
Size const &terminal_size,
|
||||
size_t io_buffer_size)
|
||||
:
|
||||
_read_buffer(read_buffer),
|
||||
_character_consumer(character_consumer),
|
||||
_terminal_size(terminal_size),
|
||||
_io_buffer(env.ram(), env.rm(), io_buffer_size)
|
||||
{ }
|
||||
|
||||
void notify_resized(Size new_size)
|
||||
{
|
||||
_terminal_size = new_size;
|
||||
|
||||
bool const client_is_out_of_date =
|
||||
(_reported_terminal_size.columns() != new_size.columns()) ||
|
||||
(_reported_terminal_size.lines() != new_size.lines());
|
||||
|
||||
if (client_is_out_of_date && _size_changed_sigh.valid())
|
||||
Signal_transmitter(_size_changed_sigh).submit();
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() override { return _terminal_size; }
|
||||
Size size() override
|
||||
{
|
||||
_reported_terminal_size = _terminal_size;
|
||||
|
||||
return _terminal_size;
|
||||
}
|
||||
|
||||
bool avail() override { return !_read_buffer.empty(); }
|
||||
|
||||
@ -104,6 +121,13 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
_read_buffer.sigh(cap);
|
||||
}
|
||||
|
||||
void size_changed_sigh(Signal_context_capability cap) override
|
||||
{
|
||||
_size_changed_sigh = cap;
|
||||
|
||||
notify_resized(_terminal_size);
|
||||
}
|
||||
|
||||
size_t read(void *, size_t) override { return 0; }
|
||||
size_t write(void const *, size_t) override { return 0; }
|
||||
};
|
||||
@ -116,23 +140,30 @@ class Terminal::Root_component : public Genode::Root_component<Session_component
|
||||
Env &_env;
|
||||
Read_buffer &_read_buffer;
|
||||
Character_consumer &_character_consumer;
|
||||
Session::Size &_terminal_size;
|
||||
Session::Size _terminal_size { };
|
||||
|
||||
Registry<Registered<Session_component> > _sessions { };
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *)
|
||||
Session_component *_create_session(const char *) override
|
||||
{
|
||||
/*
|
||||
* XXX read I/O buffer size from args
|
||||
*/
|
||||
size_t io_buffer_size = 4096;
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_env,
|
||||
_read_buffer,
|
||||
_character_consumer,
|
||||
_terminal_size,
|
||||
io_buffer_size);
|
||||
Session_component &session = *new (md_alloc())
|
||||
Registered<Session_component>(_sessions,
|
||||
_env,
|
||||
_read_buffer,
|
||||
_character_consumer,
|
||||
io_buffer_size);
|
||||
|
||||
/* propagate current terminal size to client */
|
||||
session.notify_resized(_terminal_size);
|
||||
|
||||
return &session;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -143,15 +174,21 @@ class Terminal::Root_component : public Genode::Root_component<Session_component
|
||||
Root_component(Env &env,
|
||||
Allocator &md_alloc,
|
||||
Read_buffer &read_buffer,
|
||||
Character_consumer &character_consumer,
|
||||
Session::Size &terminal_size)
|
||||
Character_consumer &character_consumer)
|
||||
:
|
||||
Genode::Root_component<Session_component>(env.ep(), md_alloc),
|
||||
_env(env),
|
||||
_read_buffer(read_buffer),
|
||||
_character_consumer(character_consumer),
|
||||
_terminal_size(terminal_size)
|
||||
_character_consumer(character_consumer)
|
||||
{ }
|
||||
|
||||
void notify_resized(Session::Size size)
|
||||
{
|
||||
_terminal_size = size;
|
||||
|
||||
_sessions.for_each([&] (Session_component &session) {
|
||||
session.notify_resized(size); });
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SESSION_H_ */
|
||||
|
@ -330,6 +330,9 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
|
||||
_read_buffer.sigh(cap);
|
||||
}
|
||||
|
||||
void size_changed_sigh(Genode::Signal_context_capability cap) override
|
||||
{ }
|
||||
|
||||
Genode::size_t read(void *buf, Genode::size_t) override { return 0; }
|
||||
Genode::size_t write(void const *buf, Genode::size_t) override { return 0; }
|
||||
};
|
||||
|
@ -107,6 +107,11 @@ class Terminal::Session_client : public Genode::Rpc_client<Session>
|
||||
call<Rpc_read_avail_sigh>(cap);
|
||||
}
|
||||
|
||||
void size_changed_sigh(Genode::Signal_context_capability cap)
|
||||
{
|
||||
call<Rpc_size_changed_sigh>(cap);
|
||||
}
|
||||
|
||||
Genode::size_t io_buffer_size() const { return _io_buffer.size(); }
|
||||
};
|
||||
|
||||
|
@ -93,6 +93,11 @@ struct Terminal::Session : Genode::Session
|
||||
*/
|
||||
virtual void read_avail_sigh(Genode::Signal_context_capability cap) = 0;
|
||||
|
||||
/**
|
||||
* Register signal handler to be notified on terminal-size changes
|
||||
*/
|
||||
virtual void size_changed_sigh(Genode::Signal_context_capability cap) = 0;
|
||||
|
||||
|
||||
/*******************
|
||||
** RPC interface **
|
||||
@ -104,11 +109,12 @@ struct Terminal::Session : Genode::Session
|
||||
GENODE_RPC(Rpc_write, Genode::size_t, _write, Genode::size_t);
|
||||
GENODE_RPC(Rpc_connected_sigh, void, connected_sigh, Genode::Signal_context_capability);
|
||||
GENODE_RPC(Rpc_read_avail_sigh, void, read_avail_sigh, Genode::Signal_context_capability);
|
||||
GENODE_RPC(Rpc_size_changed_sigh, void, size_changed_sigh, Genode::Signal_context_capability);
|
||||
GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, _dataspace);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_size, Rpc_avail, Rpc_read, Rpc_write,
|
||||
Rpc_connected_sigh, Rpc_read_avail_sigh,
|
||||
Rpc_dataspace);
|
||||
Rpc_size_changed_sigh, Rpc_dataspace);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__TERMINAL_SESSION__TERMINAL_SESSION_H_ */
|
||||
|
@ -78,6 +78,11 @@ class Uart::Session_client : public Genode::Rpc_client<Session>
|
||||
_terminal.read_avail_sigh(cap);
|
||||
}
|
||||
|
||||
void size_changed_sigh(Genode::Signal_context_capability cap)
|
||||
{
|
||||
_terminal.size_changed_sigh(cap);
|
||||
}
|
||||
|
||||
Genode::size_t io_buffer_size() const
|
||||
{
|
||||
return _terminal.io_buffer_size();
|
||||
|
@ -152,9 +152,9 @@ class Uart::Session_component : public Rpc_object<Uart::Session,
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() { return _size; }
|
||||
Size size() override { return _size; }
|
||||
|
||||
bool avail() { return _driver.char_avail(); }
|
||||
bool avail() override { return _driver.char_avail(); }
|
||||
|
||||
Genode::size_t _read(Genode::size_t dst_len)
|
||||
{
|
||||
@ -183,7 +183,7 @@ class Uart::Session_component : public Rpc_object<Uart::Session,
|
||||
Genode::Dataspace_capability _dataspace() {
|
||||
return _io_buffer.cap(); }
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability sigh)
|
||||
void connected_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
/*
|
||||
* Immediately reflect connection-established signal to the
|
||||
@ -193,15 +193,17 @@ class Uart::Session_component : public Rpc_object<Uart::Session,
|
||||
Genode::Signal_transmitter(sigh).submit();
|
||||
}
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh)
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
_char_avail.sigh = sigh;
|
||||
|
||||
if (_driver.char_avail()) _char_avail();
|
||||
}
|
||||
|
||||
Genode::size_t read(void *, Genode::size_t) { return 0; }
|
||||
Genode::size_t write(void const *, Genode::size_t) { return 0; }
|
||||
void size_changed_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
Genode::size_t read(void *, Genode::size_t) override { return 0; }
|
||||
Genode::size_t write(void const *, Genode::size_t) override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -111,9 +111,9 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() { return Size(0, 0); }
|
||||
Size size() override { return Size(0, 0); }
|
||||
|
||||
bool avail() { return false; }
|
||||
bool avail() override { return false; }
|
||||
|
||||
size_t _read(size_t) { return 0; }
|
||||
|
||||
@ -134,7 +134,9 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
|
||||
Dataspace_capability _dataspace() { return _io_buffer.cap(); }
|
||||
|
||||
void read_avail_sigh(Signal_context_capability) { }
|
||||
void read_avail_sigh(Signal_context_capability) override { }
|
||||
|
||||
void size_changed_sigh(Signal_context_capability) override { }
|
||||
|
||||
void connected_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
@ -146,8 +148,8 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
Signal_transmitter(sigh).submit();
|
||||
}
|
||||
|
||||
size_t read(void *, size_t) { return 0; }
|
||||
size_t write(void const *, size_t) { return 0; }
|
||||
size_t read(void *, size_t) override { return 0; }
|
||||
size_t write(void const *, size_t) override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -68,9 +68,9 @@ namespace Terminal_crosslink {
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size();
|
||||
Size size() override;
|
||||
|
||||
bool avail();
|
||||
bool avail() override;
|
||||
|
||||
Genode::size_t _read(Genode::size_t dst_len);
|
||||
|
||||
@ -78,12 +78,14 @@ namespace Terminal_crosslink {
|
||||
|
||||
Genode::Dataspace_capability _dataspace();
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability sigh);
|
||||
void connected_sigh(Genode::Signal_context_capability sigh) override;
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh);
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh) override;
|
||||
|
||||
Genode::size_t read(void *, Genode::size_t);
|
||||
Genode::size_t write(void const *, Genode::size_t);
|
||||
void size_changed_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
Genode::size_t read(void *, Genode::size_t) override;
|
||||
Genode::size_t write(void const *, Genode::size_t) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user