diff --git a/repos/demo/include/scout/nitpicker_graphics_backend.h b/repos/demo/include/scout/nitpicker_graphics_backend.h index 0964aa583..27196cbe4 100644 --- a/repos/demo/include/scout/nitpicker_graphics_backend.h +++ b/repos/demo/include/scout/nitpicker_graphics_backend.h @@ -16,7 +16,6 @@ /* Genode includes */ #include -#include #include /* Scout includes */ @@ -53,19 +52,25 @@ class Scout::Nitpicker_graphics_backend : public Graphics_backend void *_fb_local_base = { _map_fb_ds() }; - Point _position; - Area _view_size; - Nitpicker::View_client _view; - Canvas_base *_canvas[2]; - bool _flip_state = { false }; + typedef Nitpicker::Session::View_handle View_handle; + + Point _position; + Area _view_size; + View_handle _view; + Canvas_base *_canvas[2]; + bool _flip_state = { false }; void _update_viewport() { - _view.viewport(_position.x(), _position.y(), - _view_size.w(), _view_size.h(), - 0, - _flip_state ? -_max_size.h() : 0, - true); + typedef Nitpicker::Session::Command Command; + + Nitpicker::Rect rect(_position, _view_size); + _nitpicker.enqueue(_view, rect); + + Nitpicker::Point offset(0, _flip_state ? -_max_size.h() : 0); + _nitpicker.enqueue(_view, offset); + + _nitpicker.execute(); } void _refresh_view(Rect rect) @@ -146,7 +151,9 @@ class Scout::Nitpicker_graphics_backend : public Graphics_backend void bring_to_front() { - _view.stack(Nitpicker::View_capability(), true, true); + typedef Nitpicker::Session::Command Command; + _nitpicker.enqueue(_view); + _nitpicker.execute(); } void view_area(Area area) diff --git a/repos/demo/src/app/backdrop/main.cc b/repos/demo/src/app/backdrop/main.cc index ec6e2797f..bbd1269af 100644 --- a/repos/demo/src/app/backdrop/main.cc +++ b/repos/demo/src/app/backdrop/main.cc @@ -16,7 +16,6 @@ /* Genode includes */ #include -#include #include #include #include @@ -241,8 +240,7 @@ int main(int argc, char **argv) nitpicker.buffer(mode, false); static Framebuffer::Session_client framebuffer(nitpicker.framebuffer_session()); - Nitpicker::View_capability view_cap = nitpicker.create_view(); - static Nitpicker::View_client view(view_cap); + Nitpicker::Session::View_handle view_handle = nitpicker.create_view(); if (mode.format() != Framebuffer::Mode::RGB565) { printf("Error: Color mode %d not supported\n", (int)mode.format()); @@ -256,9 +254,14 @@ int main(int argc, char **argv) convert_png_to_rgb565(png_data, fb, mode.width(), mode.height()); /* display view behind all others */ - nitpicker.background(view_cap); - view.viewport(0, 0, mode.width(), mode.height(), 0, 0, false); - view.stack(Nitpicker::View_capability(), false, false); + typedef Nitpicker::Session::Command Command; + nitpicker.enqueue(view_handle); + Nitpicker::Rect rect(Nitpicker::Point(), + Nitpicker::Area(mode.width(), mode.height())); + nitpicker.enqueue(view_handle, rect); + nitpicker.enqueue(view_handle); + nitpicker.execute(); + framebuffer.refresh(0, 0, mode.width(), mode.height()); sleep_forever(); diff --git a/repos/demo/src/server/nitlog/main.cc b/repos/demo/src/server/nitlog/main.cc index 48a9b6dea..d602b9732 100644 --- a/repos/demo/src/server/nitlog/main.cc +++ b/repos/demo/src/server/nitlog/main.cc @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -343,40 +342,42 @@ class Log_view { private: - Nitpicker::View_capability _cap; + Nitpicker::Session_client &_nitpicker; + Nitpicker::Point _pos; + Nitpicker::Area _size; + Nitpicker::Session::View_handle _handle; - int _x, _y, _w, _h; + typedef Nitpicker::Session::Command Command; public: - Log_view(Nitpicker::Session *nitpicker, - int x, int y, int w, int h) + Log_view(Nitpicker::Session_client &nitpicker, Nitpicker::Rect geometry) : - _x(x), _y(y), _w(w), _h(h) + _nitpicker(nitpicker), + _pos(geometry.p1()), + _size(geometry.area()), + _handle(nitpicker.create_view()) { - using namespace Nitpicker; - - _cap = nitpicker->create_view(); - View_client(_cap).viewport(_x, _y, _w, _h, 0, 0, true); - View_client(_cap).stack(Nitpicker::View_capability(), true, true); + move(_pos); + top(); } void top() { - Nitpicker::View_client(_cap).stack(Nitpicker::View_capability(), true, true); + _nitpicker.enqueue(_handle); + _nitpicker.execute(); } - void move(int x, int y) + void move(Nitpicker::Point pos) { - _x = x, _y = y; - Nitpicker::View_client(_cap).viewport(_x, _y, _w, _h, 0, 0, true); + _pos = pos; + + Nitpicker::Rect rect(_pos, _size); + _nitpicker.enqueue(_handle, rect); + _nitpicker.execute(); } - /** - * Accessors - */ - int x() { return _x; } - int y() { return _y; } + Nitpicker::Point pos() const { return _pos; } }; @@ -424,7 +425,9 @@ int main(int argc, char **argv) canvas.clip(::Rect(::Point(1, 1), ::Area(log_win_w - 2, log_win_h - 2))); /* create view for log window */ - Log_view log_view(&nitpicker, 20, 20, log_win_w, log_win_h); + Nitpicker::Rect log_view_geometry(Nitpicker::Point(20, 20), + Nitpicker::Area(log_win_w, log_win_h)); + Log_view log_view(nitpicker, log_view_geometry); /* create root interface for service */ static Log_root_component log_root(&ep, &sliced_heap, &log_window); @@ -434,7 +437,8 @@ int main(int argc, char **argv) /* handle input events */ Input::Event *ev_buf = env()->rm_session()->attach(nitpicker.input()->dataspace()); - int omx = 0, omy = 0, key_cnt = 0; + Nitpicker::Point old_mouse_pos; + unsigned key_cnt = 0; while (1) { while (!nitpicker.input()->is_pending()) { @@ -450,16 +454,17 @@ int main(int argc, char **argv) if (ev->type() == Input::Event::PRESS) key_cnt++; if (ev->type() == Input::Event::RELEASE) key_cnt--; + Nitpicker::Point mouse_pos(ev->ax(), ev->ay()); + /* move view */ if (ev->type() == Input::Event::MOTION && key_cnt > 0) - log_view.move(log_view.x() + ev->ax() - omx, - log_view.y() + ev->ay() - omy); + log_view.move(log_view.pos() + mouse_pos - old_mouse_pos); /* find selected view and bring it to front */ if (ev->type() == Input::Event::PRESS && key_cnt == 1) log_view.top(); - omx = ev->ax(); omy = ev->ay(); + old_mouse_pos = mouse_pos; } } return 0; diff --git a/repos/libports/include/qt5/qnitpickerviewwidget/qnitpickerviewwidget.h b/repos/libports/include/qt5/qnitpickerviewwidget/qnitpickerviewwidget.h index 7d504db35..de87b1b61 100644 --- a/repos/libports/include/qt5/qnitpickerviewwidget/qnitpickerviewwidget.h +++ b/repos/libports/include/qt5/qnitpickerviewwidget/qnitpickerviewwidget.h @@ -19,8 +19,7 @@ #include #endif -#include -#include +#include class QNitpickerViewWidget : public QWidget { @@ -38,7 +37,10 @@ private slots: void destroyed(QObject *obj = 0); protected: - Nitpicker::View_client *vc; + + Nitpicker::Session_client *nitpicker; + Nitpicker::Session::View_handle view_handle; + int orig_w; int orig_h; int orig_buf_x; @@ -51,7 +53,9 @@ protected: public: QNitpickerViewWidget(QWidget *parent =0); ~QNitpickerViewWidget(); - void setNitpickerView(Nitpicker::View_capability view, int buf_x, int buf_y, int w, int h); + void setNitpickerView(Nitpicker::Session_client *nitpicker, + Nitpicker::Session::View_handle view_handle, + int buf_x, int buf_y, int w, int h); }; #endif // QNITPICKERVIEWWIDGET_H diff --git a/repos/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc b/repos/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc index 8e3d778bf..1f4eb4861 100644 --- a/repos/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc +++ b/repos/libports/src/app/qt5/qt_avplay/framebuffer_session_component.cc @@ -13,11 +13,12 @@ /* Genode includes */ #include -#include +#include #include #include #include "framebuffer_session_component.h" +#include namespace Framebuffer { @@ -49,9 +50,22 @@ namespace Framebuffer { _limited_size(session_arg(args, "fb_height"), max_height), _nitpicker.mode().format()); _nitpicker.buffer(mode, false); - Nitpicker::View_capability nitpicker_view_cap = _nitpicker.create_view(); + + QNitpickerPlatformWindow *platform_window = + dynamic_cast(nitpicker_view_widget + .window()->windowHandle()->handle()); + + Nitpicker::Session::View_handle parent_view_handle = + _nitpicker.view_handle(platform_window->view_cap()); + + Nitpicker::Session::View_handle nitpicker_view_handle = + _nitpicker.create_view(parent_view_handle); + + _nitpicker.release_view_handle(parent_view_handle); + Mode _mode = _framebuffer.mode(); - nitpicker_view_widget.setNitpickerView(nitpicker_view_cap, + nitpicker_view_widget.setNitpickerView(&_nitpicker, + nitpicker_view_handle, 0, 0, _mode.width(), _mode.height()); diff --git a/repos/libports/src/lib/qt5/qnitpickerviewwidget/qnitpickerviewwidget.cpp b/repos/libports/src/lib/qt5/qnitpickerviewwidget/qnitpickerviewwidget.cpp index d6cebe3b2..c38bddc5e 100644 --- a/repos/libports/src/lib/qt5/qnitpickerviewwidget/qnitpickerviewwidget.cpp +++ b/repos/libports/src/lib/qt5/qnitpickerviewwidget/qnitpickerviewwidget.cpp @@ -20,26 +20,29 @@ QNitpickerViewWidget::QNitpickerViewWidget(QWidget *parent) - : QWidget(parent), vc(0), orig_w(0), orig_h(0), orig_buf_x(0), orig_buf_y(0) + : QWidget(parent), nitpicker(0), orig_w(0), orig_h(0), orig_buf_x(0), orig_buf_y(0) { } -void QNitpickerViewWidget::setNitpickerView(Nitpicker::View_capability view, int buf_x, int buf_y, int w, int h) +void QNitpickerViewWidget::setNitpickerView(Nitpicker::Session_client *new_nitpicker, + Nitpicker::Session::View_handle new_view_handle, + int buf_x, int buf_y, int w, int h) { orig_buf_x = buf_x; orig_buf_y = buf_y; orig_w = w; orig_h = h; // PDBG("orig_w = %d, orig_h = %d", orig_w, orig_h); - vc = new Nitpicker::View_client(view); + + nitpicker = new_nitpicker; + view_handle = new_view_handle; setFixedSize(orig_w, orig_h); } QNitpickerViewWidget::~QNitpickerViewWidget() { - delete vc; } @@ -61,15 +64,27 @@ void QNitpickerViewWidget::hideEvent(QHideEvent *event) #endif QWidget::hideEvent(event); - if (vc) - vc->viewport(mapToGlobal(pos()).x(), mapToGlobal(pos()).y(), 0, 0, orig_buf_x, orig_buf_y, 1); + if (nitpicker) { + + typedef Nitpicker::Session::Command Command; + + Nitpicker::Rect geometry(Nitpicker::Point(mapToGlobal(pos()).x(), + mapToGlobal(pos()).y()), + Nitpicker::Area(0, 0)); + nitpicker->enqueue(view_handle, geometry); + + Nitpicker::Point offset(orig_buf_x, orig_buf_y); + nitpicker->enqueue(view_handle, offset); + + nitpicker->execute(); + } } void QNitpickerViewWidget::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); - if (!vc) + if (!nitpicker) return; /* mark all sliders as unchecked */ @@ -221,19 +236,20 @@ void QNitpickerViewWidget::paintEvent(QPaintEvent *event) } } + typedef Nitpicker::Session::Command Command; + /* argument to mapToGlobal() is relative to the Widget's origin * the plugin view starts at (0, 0) */ if (mask().isEmpty()) { -/* PDBG("x0 = %d, y0 = %d, w = %d, h = %d, buf_x = %d, buf_y = %d", - x0, y0, w, h, orig_buf_x + diff_x, orig_buf_y + diff_y); */ - vc->viewport(x0, - y0, - /*qMin(width(), w)*/w, - /*qMin(height(), h)*/h, - orig_buf_x + diff_x, - orig_buf_y + diff_y, - false); +// PDBG("x0 = %d, y0 = %d, w = %d, h = %d, buf_x = %d, buf_y = %d", +// x0, y0, w, h, orig_buf_x + diff_x, orig_buf_y + diff_y); + + Nitpicker::Rect geometry(Nitpicker::Point(x0, y0), + Nitpicker::Area(w, h)); + nitpicker->enqueue(view_handle, geometry); + Nitpicker::Point offset(orig_buf_x + diff_x, orig_buf_y + diff_y); + nitpicker->enqueue(view_handle, offset); } else { /* PDBG("x = %d, y = %d, w = %d, h = %d, buf_x = %d, buf_y = %d", mapToGlobal(mask().boundingRect().topLeft()).x(), @@ -241,19 +257,29 @@ void QNitpickerViewWidget::paintEvent(QPaintEvent *event) mask().boundingRect().width(), mask().boundingRect().height(), orig_buf_x + diff_x, orig_buf_y + diff_y); */ - vc->viewport(mapToGlobal(mask().boundingRect().topLeft()).x(), - mapToGlobal(mask().boundingRect().topLeft()).y(), - mask().boundingRect().width(), - mask().boundingRect().height(), - orig_buf_x + diff_x, - orig_buf_y + diff_y, - false); + + Nitpicker::Rect const + geometry(Nitpicker::Point(mapToGlobal(mask().boundingRect().topLeft()).x(), + mapToGlobal(mask().boundingRect().topLeft()).y()), + Nitpicker::Area(mask().boundingRect().width(), + mask().boundingRect().height())); + nitpicker->enqueue(view_handle, geometry); + + Nitpicker::Point offset(orig_buf_x + diff_x, orig_buf_y + diff_y); + nitpicker->enqueue(view_handle, offset); } /* bring the plugin view to the front of the Qt window */ QNitpickerPlatformWindow *platform_window = dynamic_cast(window()->windowHandle()->handle()); - vc->stack(platform_window->view_cap(), false, true); + + Nitpicker::Session::View_handle neighbor_handle = + nitpicker->view_handle(platform_window->view_cap()); + + nitpicker->enqueue(view_handle, neighbor_handle); + nitpicker->execute(); + + nitpicker->release_view_handle(neighbor_handle); } #if 0 void QNitpickerViewWidget::windowEvent(QWSWindow *window, diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp index 821d87391..3de18832f 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp @@ -13,7 +13,7 @@ /* Genode includes */ -#include +#include /* Qt includes */ #include @@ -124,20 +124,29 @@ void QNitpickerPlatformWindow::_process_key_event(Input::Event *ev) _keyboard_handler.processKeycode(keycode, pressed, false); } -Nitpicker::View_capability QNitpickerPlatformWindow::_create_view() +Nitpicker::Session::View_handle QNitpickerPlatformWindow::_create_view() { if (window()->type() == Qt::Desktop) - return Nitpicker::View_capability(); + return Nitpicker::Session::View_handle(); if (window()->type() == Qt::Dialog) - return _nitpicker_session.create_view(Nitpicker::View_capability()); + return _nitpicker_session.create_view(); if (window()->transientParent()) { QNitpickerPlatformWindow *parent_platform_window = static_cast(window()->transientParent()->handle()); - return _nitpicker_session.create_view(parent_platform_window->view_cap()); + + Nitpicker::Session::View_handle parent_handle = + _nitpicker_session.view_handle(parent_platform_window->view_cap()); + + Nitpicker::Session::View_handle result = + _nitpicker_session.create_view(parent_handle); + + _nitpicker_session.release_view_handle(parent_handle); + + return result; } else - return _nitpicker_session.create_view(Nitpicker::View_capability()); + return _nitpicker_session.create_view(); } void QNitpickerPlatformWindow::_adjust_and_set_geometry(const QRect &rect) @@ -163,7 +172,7 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_ : QPlatformWindow(window), _framebuffer_session(_nitpicker_session.framebuffer_session()), _framebuffer(0), - _view_cap(_create_view()), + _view_handle(_create_view()), _input_session(_nitpicker_session.input_session()), _timer(this), _keyboard_handler("", -1, false, false, ""), @@ -180,10 +189,12 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_ _ev_buf = static_cast (Genode::env()->rm_session()->attach(_input_session.dataspace())); - if (_view_cap.valid()) { + if (_view_handle.valid()) { + /* bring the view to the top */ - Nitpicker::View_client(_view_cap).stack(Nitpicker::View_capability(), - true, false); + typedef Nitpicker::Session::Command Command; + _nitpicker_session.enqueue(_view_handle); + _nitpicker_session.execute(); } connect(_timer, SIGNAL(timeout()), this, SLOT(handle_events())); @@ -227,11 +238,12 @@ void QNitpickerPlatformWindow::setGeometry(const QRect &rect) if (window()->isVisible()) { QRect g(geometry()); - Nitpicker::View_client(_view_cap).viewport(g.x(), - g.y(), - g.width(), - g.height(), - 0, 0, true); + + typedef Nitpicker::Session::Command Command; + _nitpicker_session.enqueue(_view_handle, + Nitpicker::Rect(Nitpicker::Point(g.x(), g.y()), + Nitpicker::Area(g.width(), g.height()))); + _nitpicker_session.execute(); } if (qnpw_verbose) @@ -257,15 +269,23 @@ void QNitpickerPlatformWindow::setVisible(bool visible) if (qnpw_verbose) qDebug() << "QNitpickerPlatformWindow::setVisible(" << visible << ")"; + typedef Nitpicker::Session::Command Command; + if (visible) { QRect g = geometry(); - Nitpicker::View_client(_view_cap).viewport(g.x(), g.y(), - g.width(), - g.height(), - 0, 0, true); - } else - Nitpicker::View_client(_view_cap).viewport(0, 0, 0, 0, 0, 0, - false); + + _nitpicker_session.enqueue(_view_handle, + Nitpicker::Rect(Nitpicker::Point(g.x(), g.y()), + Nitpicker::Area(g.width(), g.height()))); + } else { + + _nitpicker_session.enqueue(_view_handle, + Nitpicker::Rect(Nitpicker::Point(), Nitpicker::Area(0, 0))); + } + + _nitpicker_session.execute(); + + QPlatformWindow::setVisible(visible); @@ -322,8 +342,12 @@ void QNitpickerPlatformWindow::setWindowTitle(const QString &title) _title = title.toLocal8Bit(); - if (_view_cap.valid()) - Nitpicker::View_client(_view_cap).title(_title.constData()); + typedef Nitpicker::Session::Command Command; + + if (_view_handle.valid()) { + _nitpicker_session.enqueue(_view_handle, _title.constData()); + _nitpicker_session.execute(); + } if (qnpw_verbose) qDebug() << "QNitpickerPlatformWindow::setWindowTitle() finished"; @@ -346,8 +370,9 @@ void QNitpickerPlatformWindow::setWindowIcon(const QIcon &icon) void QNitpickerPlatformWindow::raise() { /* bring the view to the top */ - Nitpicker::View_client(_view_cap).stack(Nitpicker::View_capability(), - true, false); + _nitpicker_session.enqueue(_view_handle); + _nitpicker_session.execute(); + QPlatformWindow::raise(); } @@ -518,7 +543,8 @@ void QNitpickerPlatformWindow::egl_surface(EGLSurface egl_surface) Nitpicker::View_capability QNitpickerPlatformWindow::view_cap() const { - return _view_cap; + QNitpickerPlatformWindow *npw = const_cast(this); + return npw->_nitpicker_session.view_capability(_view_handle); } void QNitpickerPlatformWindow::handle_events() diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h index 022f06c03..df2f4c2a7 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h @@ -37,24 +37,24 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow private: - Nitpicker::Connection _nitpicker_session; - Framebuffer::Session_client _framebuffer_session; - unsigned char *_framebuffer; - Nitpicker::View_capability _view_cap; - Input::Session_client _input_session; - Input::Event *_ev_buf; - QMember _timer; - Qt::MouseButtons _mouse_button_state; - QEvdevKeyboardHandler _keyboard_handler; - QByteArray _title; - bool _resize_handle; - bool _decoration; - EGLSurface _egl_surface; + Nitpicker::Connection _nitpicker_session; + Framebuffer::Session_client _framebuffer_session; + unsigned char *_framebuffer; + Nitpicker::Session::View_handle _view_handle; + Input::Session_client _input_session; + Input::Event *_ev_buf; + QMember _timer; + Qt::MouseButtons _mouse_button_state; + QEvdevKeyboardHandler _keyboard_handler; + QByteArray _title; + bool _resize_handle; + bool _decoration; + EGLSurface _egl_surface; void _process_mouse_event(Input::Event *ev); void _process_key_event(Input::Event *ev); - Nitpicker::View_capability _create_view(); + Nitpicker::Session::View_handle _create_view(); void _adjust_and_set_geometry(const QRect &rect); public: diff --git a/repos/os/include/loader_session/loader_session.h b/repos/os/include/loader_session/loader_session.h index f1516ed0c..b2c7a62ac 100644 --- a/repos/os/include/loader_session/loader_session.h +++ b/repos/os/include/loader_session/loader_session.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/repos/os/include/nitpicker_session/client.h b/repos/os/include/nitpicker_session/client.h index fd94a6a21..c5f3032fd 100644 --- a/repos/os/include/nitpicker_session/client.h +++ b/repos/os/include/nitpicker_session/client.h @@ -16,38 +16,91 @@ #include #include +#include namespace Nitpicker { struct Session_client; } -struct Nitpicker::Session_client : public Genode::Rpc_client +class Nitpicker::Session_client : public Genode::Rpc_client { - explicit Session_client(Session_capability session) - : Rpc_client(session) { } + private: - Framebuffer::Session_capability framebuffer_session() override { - return call(); } + Genode::Attached_dataspace _command_ds; - Input::Session_capability input_session() override { - return call(); } + Command_buffer &_command_buffer; - View_capability create_view(View_capability parent = View_capability()) override { - return call(parent); } + public: - void destroy_view(View_capability view) override { - call(view); } + explicit Session_client(Session_capability session) + : + Rpc_client(session), + _command_ds(command_dataspace()), + _command_buffer(*_command_ds.local_addr()) + { } - int background(View_capability view) override { - return call(view); } + Framebuffer::Session_capability framebuffer_session() override { + return call(); } - Framebuffer::Mode mode() override { - return call(); } + Input::Session_capability input_session() override { + return call(); } - void buffer(Framebuffer::Mode mode, bool alpha) override { - call(mode, alpha); } + View_handle create_view(View_handle parent = View_handle()) override { + return call(parent); } - void focus(Nitpicker::Session_capability session) override { - call(session); } + void destroy_view(View_handle view) override { + call(view); } + + View_handle view_handle(View_capability view, + View_handle handle = View_handle()) override + { + return call(view, handle); + } + + View_capability view_capability(View_handle handle) override { + return call(handle); } + + void release_view_handle(View_handle handle) override { + call(handle); } + + Genode::Dataspace_capability command_dataspace() override { + return call(); } + + void execute() override + { + call(); + _command_buffer.reset(); + } + + Framebuffer::Mode mode() override { + return call(); } + + void buffer(Framebuffer::Mode mode, bool alpha) override { + call(mode, alpha); } + + void focus(Nitpicker::Session_capability session) override { + call(session); } + + /** + * Enqueue command to command buffer + * + * The submitted command is not executed immediately. To execute a + * batch of enqueued commands, the 'execute' function must be called. + * Only in the corner case when there is not space left in the command + * buffer, the 'execute' is called to make room in the buffer. + */ + template + void enqueue(ARGS... args) + { + enqueue(Command( CMD { args... } )); + } + + void enqueue(Command const &command) + { + if (_command_buffer.is_full()) + execute(); + + _command_buffer.enqueue(command); + } }; #endif /* _INCLUDE__NITPICKER_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/nitpicker_session/connection.h b/repos/os/include/nitpicker_session/connection.h index 0d7dbe4cc..984f297b1 100644 --- a/repos/os/include/nitpicker_session/connection.h +++ b/repos/os/include/nitpicker_session/connection.h @@ -44,7 +44,7 @@ class Nitpicker::Connection : public Genode::Connection, * Declare ram-quota donation */ using Genode::Arg_string; - enum { SESSION_METADATA = 20*1024 }; + enum { SESSION_METADATA = 36*1024 }; Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", SESSION_METADATA); if (stay_top) diff --git a/repos/os/include/nitpicker_session/nitpicker_session.h b/repos/os/include/nitpicker_session/nitpicker_session.h index cde05aa4c..6c8616fc0 100644 --- a/repos/os/include/nitpicker_session/nitpicker_session.h +++ b/repos/os/include/nitpicker_session/nitpicker_session.h @@ -17,13 +17,20 @@ #define _INCLUDE__NITPICKER_SESSION__NITPICKER_SESSION_H_ #include +#include +#include #include #include -#include namespace Nitpicker { using Genode::size_t; + struct View; + typedef Genode::Capability View_capability; struct Session; + typedef Genode::Surface_base::Rect Rect; + typedef Genode::Surface_base::Point Point; + typedef Genode::Surface_base::Area Area; + using Genode::Meta::Type_tuple; } @@ -32,9 +39,144 @@ struct Nitpicker::Session : Genode::Session static const char *service_name() { return "Nitpicker"; } /** - * Exception type + * Session-local view handle + * + * When issuing commands to nitpicker via the 'execute' function, views + * are referenced by session-local handles. + */ + typedef Genode::Handle View_handle; + + + struct Command + { + enum Opcode { OP_GEOMETRY, OP_OFFSET, + OP_TO_FRONT, OP_TO_BACK, OP_BACKGROUND, + OP_TITLE, OP_NOP }; + + /* + * Argument structures for nitpicker's command interface + */ + + struct Nop { static Opcode opcode() { return OP_NOP; } }; + + struct Geometry + { + static Opcode opcode() { return OP_GEOMETRY; } + View_handle view; + Rect rect; + }; + + struct Offset + { + static Opcode opcode() { return OP_OFFSET; } + View_handle view; + Point offset; + }; + + struct To_front + { + static Opcode opcode() { return OP_TO_FRONT; } + View_handle view; + View_handle neighbor; + }; + + struct To_back + { + static Opcode opcode() { return OP_TO_BACK; } + View_handle view; + View_handle neighbor; + }; + + struct Background + { + static Opcode opcode() { return OP_BACKGROUND; } + View_handle view; + }; + + struct Title + { + static Opcode opcode() { return OP_TITLE; } + View_handle view; + Genode::String<64> title; + }; + + Opcode opcode; + union + { + Nop nop; + Geometry geometry; + Offset offset; + To_front to_front; + To_back to_back; + Background background; + Title title; + }; + + Command() : opcode(OP_NOP) { } + + template + Command(ARGS args) + { + opcode = ARGS::opcode(); + reinterpret_cast(nop) = args; + } + }; + + + /** + * Command buffer shared between nitpicker and client + */ + class Command_buffer + { + public: + + enum { MAX_COMMANDS = 64 }; + + private: + + unsigned _num = 0; + + Command _commands[MAX_COMMANDS]; + + public: + + bool is_full() const { return _num >= MAX_COMMANDS; } + + unsigned num() const + { + /* copy out _num value to avoid use-after-check problems */ + unsigned const num = _num; + return num <= MAX_COMMANDS ? num : 0; + } + + void reset() { _num = 0; } + + /** + * Enqueue command + * + * The command will be dropped if the buffer is full. Check for this + * condition by calling 'is_full()' prior calling this function. + */ + void enqueue(Command const &command) + { + if (!is_full()) + _commands[_num++] = command; + } + + Command get(unsigned i) + { + if (i >= MAX_COMMANDS) return Command(Command::Nop()); + + return _commands[i]; + } + + }; + + /** + * Exception types */ struct Out_of_metadata : Genode::Exception { }; + struct Invalid_handle : Genode::Exception { }; virtual ~Session() { } @@ -53,24 +195,57 @@ struct Nitpicker::Session : Genode::Session * * \param parent parent view * - * \return capability to a new view + * \throw Invalid_handle + * \return handle for new view * * The 'parent' argument allows the client to use the location of an * existing view as the coordinate origin for the to-be-created view. - * If an invalid capability is specified (default), the view will be a + * If an invalid handle is specified (default), the view will be a * top-level view. */ - virtual View_capability create_view(View_capability parent = View_capability()) = 0; + virtual View_handle create_view(View_handle parent = View_handle()) = 0; /** * Destroy view */ - virtual void destroy_view(View_capability view) = 0; + virtual void destroy_view(View_handle) = 0; /** - * Define view that is used as desktop background + * Return session-local handle for the specified view + * + * The handle returned by this functions can be used to issue commands + * via the 'execute' function. + * + * \param handle designated view handle to be assigned to the imported + * view. By default, a new handle will be allocated. + * + * \throw Out_of_metadata */ - virtual int background(View_capability view) = 0; + virtual View_handle view_handle(View_capability, + View_handle handle = View_handle()) = 0; + + /** + * Request view capability for a given handle + * + * The returned view capability can be used to share the view with another + * session. + */ + virtual View_capability view_capability(View_handle) = 0; + + /** + * Release session-local view handle + */ + virtual void release_view_handle(View_handle) = 0; + + /** + * Request dataspace used for issuing view commands to nitpicker + */ + virtual Genode::Dataspace_capability command_dataspace() = 0; + + /** + * Execution batch of commands contained in the command dataspace + */ + virtual void execute() = 0; /** * Return physical screen mode @@ -118,17 +293,40 @@ struct Nitpicker::Session : Genode::Session GENODE_RPC(Rpc_framebuffer_session, Framebuffer::Session_capability, framebuffer_session); GENODE_RPC(Rpc_input_session, Input::Session_capability, input_session); - GENODE_RPC(Rpc_create_view, View_capability, create_view, View_capability); - GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_capability); + GENODE_RPC_THROW(Rpc_create_view, View_handle, create_view, + GENODE_TYPE_LIST(Out_of_metadata, Invalid_handle), View_handle); + GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_handle); + GENODE_RPC_THROW(Rpc_view_handle, View_handle, view_handle, + GENODE_TYPE_LIST(Out_of_metadata), View_capability, View_handle); + GENODE_RPC(Rpc_view_capability, View_capability, view_capability, View_handle); + GENODE_RPC(Rpc_release_view_handle, void, release_view_handle, View_handle); + GENODE_RPC(Rpc_command_dataspace, Genode::Dataspace_capability, command_dataspace); + GENODE_RPC(Rpc_execute, void, execute); GENODE_RPC(Rpc_background, int, background, View_capability); GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode); GENODE_RPC(Rpc_focus, void, focus, Genode::Capability); GENODE_RPC_THROW(Rpc_buffer, void, buffer, GENODE_TYPE_LIST(Out_of_metadata), Framebuffer::Mode, bool); - GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session, - Rpc_create_view, Rpc_destroy_view, Rpc_background, - Rpc_mode, Rpc_buffer, Rpc_focus); + /* + * The 'GENODE_RPC_INTERFACE' declaration is done manually because the + * number of RPC functions exceeds the maxium arguments supported by the + * 'Type_list' template. + */ + typedef Type_tuple + > > > > > > > > > > > Rpc_functions; }; #endif /* _INCLUDE__NITPICKER_SESSION__NITPICKER_SESSION_H_ */ diff --git a/repos/os/include/nitpicker_view/capability.h b/repos/os/include/nitpicker_view/capability.h deleted file mode 100644 index e9d433448..000000000 --- a/repos/os/include/nitpicker_view/capability.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \brief Nitpicker view capability type - * \author Norman Feske - * \date 2008-08-16 - */ - -/* - * Copyright (C) 2008-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__NITPICKER_VIEW__CAPABILITY_H_ -#define _INCLUDE__NITPICKER_VIEW__CAPABILITY_H_ - -#include - -namespace Nitpicker { - - class View; - typedef Genode::Capability View_capability; -} - -#endif /* _INCLUDE__NITPICKER_VIEW__CAPABILITY_H_ */ diff --git a/repos/os/include/nitpicker_view/client.h b/repos/os/include/nitpicker_view/client.h deleted file mode 100644 index 37520bae1..000000000 --- a/repos/os/include/nitpicker_view/client.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * \brief Client-side nitpicker view interface - * \author Norman Feske - * \date 2006-08-23 - */ - -/* - * Copyright (C) 2006-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__NITPICKER_VIEW__CLIENT_H_ -#define _INCLUDE__NITPICKER_VIEW__CLIENT_H_ - -#include -#include - -namespace Nitpicker { - - struct View_client : public Genode::Rpc_client - { - explicit View_client(View_capability view) - : Genode::Rpc_client(view) { } - - int viewport(int x, int y, int w, int h, - int buf_x, int buf_y, bool redraw) { - return call(x, y, w, h, buf_x, buf_y, redraw); } - - int stack(View_capability neighbor, bool behind, bool redraw) { - return call(neighbor, behind, redraw); } - - int title(Title const &title) { - return call(title); } - }; -} - -#endif /* _INCLUDE__NITPICKER_VIEW__CLIENT_H_ */ diff --git a/repos/os/include/nitpicker_view/nitpicker_view.h b/repos/os/include/nitpicker_view/nitpicker_view.h deleted file mode 100644 index 227ba3c88..000000000 --- a/repos/os/include/nitpicker_view/nitpicker_view.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * \brief Nitpicker view interface - * \author Norman Feske - * \date 2006-08-10 - */ - -/* - * Copyright (C) 2006-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__NITPICKER_VIEW__NITPICKER_VIEW_H_ -#define _INCLUDE__NITPICKER_VIEW__NITPICKER_VIEW_H_ - -#include -#include -#include -#include - -namespace Nitpicker { - - struct View - { - virtual ~View() { } - - /** - * Define position and viewport - * - * Both attributes are handled in one function to enable atomic - * updates of position and viewport. This is the common case for - * moving an overlay window. - */ - virtual int viewport(int x, int y, int w, int h, - int buf_x, int buf_y, bool redraw = true) = 0; - - /** - * Reposition view in view stack - * - * \param neighbor neighbor view - * \param behind insert view in front (true) or - * behind (false) the specified neighbor - * \param redraw redraw affected screen region - * - * To insert a view at the top of the view stack, specify - * neighbor = invalid and behind = true. To insert a view at the - * bottom of the view stack, specify neighbor = invalid and - * behind = false. - */ - virtual int stack(View_capability neighbor = View_capability(), - bool behind = true, bool redraw = true) = 0; - - /** - * String type used as argument for the 'title' function - */ - typedef Genode::Rpc_in_buffer<64> Title; - - /** - * Assign new view title - */ - virtual int title(Title const &title) = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_viewport, int, viewport, int, int, int, int, int, int, bool); - GENODE_RPC(Rpc_stack, int, stack, View_capability, bool, bool); - GENODE_RPC(Rpc_title, int, title, Title const &); - - GENODE_RPC_INTERFACE(Rpc_viewport, Rpc_stack, Rpc_title); - }; -} - -#endif /* _INCLUDE__NITPICKER_VIEW__NITPICKER_VIEW_H_ */ diff --git a/repos/os/src/server/nit_fb/main.cc b/repos/os/src/server/nit_fb/main.cc index 8631b5af8..57406789d 100644 --- a/repos/os/src/server/nit_fb/main.cc +++ b/repos/os/src/server/nit_fb/main.cc @@ -13,7 +13,6 @@ /* Genode includes */ #include -#include #include #include #include @@ -176,9 +175,13 @@ int main(int argc, char **argv) /* * Create Nitpicker view and bring it to front */ - Nitpicker::View_client view(nitpicker.create_view()); - view.viewport(view_x, view_y, view_w, view_h, 0, 0, false); - view.stack(Nitpicker::View_capability(), true, true); + Nitpicker::Session::View_handle view = nitpicker.create_view(); + typedef Nitpicker::Session::Command Command; + Nitpicker::Rect geometry(Nitpicker::Point(view_x, view_y), + Nitpicker::Area(view_w, view_h)); + nitpicker.enqueue(view, geometry); + nitpicker.enqueue(view); + nitpicker.execute(); /* * Initialize server entry point @@ -243,7 +246,11 @@ int main(int argc, char **argv) try { config()->reload(); cfg = Config_args(); - view.viewport(cfg.xpos, cfg.ypos, cfg.width, cfg.height, 0, 0, true); + + Nitpicker::Rect geometry(Nitpicker::Point(cfg.xpos, cfg.ypos), + Nitpicker::Area(cfg.width, cfg.height)); + nitpicker.enqueue(view, geometry); + nitpicker.execute(); } catch (...) { PERR("Error while reloading config"); } diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 8118bd108..ef1d97e4d 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -43,13 +42,13 @@ namespace Input { class Session_component; } namespace Framebuffer { class Session_component; } + namespace Nitpicker { class Session_component; template class Root; struct Main; } - using Genode::size_t; using Genode::Allocator; using Genode::Rpc_entrypoint; @@ -67,6 +66,8 @@ using Genode::Signal_context_capability; using Genode::Signal_rpc_member; using Genode::Attached_ram_dataspace; using Genode::Attached_dataspace; +using Genode::Weak_ptr; +using Genode::Locked_ptr; Framebuffer::Session *tmp_fb; @@ -366,68 +367,6 @@ class Framebuffer::Session_component : public Genode::Rpc_object }; -class View_component : public Genode::List::Element, - public Genode::Rpc_object -{ - private: - - typedef Genode::Rpc_entrypoint Rpc_entrypoint; - - View_stack &_view_stack; - ::View _view; - Rpc_entrypoint &_ep; - - public: - - /** - * Constructor - */ - View_component(::Session &session, View_stack &view_stack, - Rpc_entrypoint &ep, ::View *parent_view): - _view_stack(view_stack), - _view(session, - session.stay_top() ? ::View::STAY_TOP : ::View::NOT_STAY_TOP, - ::View::NOT_TRANSPARENT, ::View::NOT_BACKGROUND, parent_view), - _ep(ep) - { } - - ::View &view() { return _view; } - - - /****************************** - ** Nitpicker view interface ** - ******************************/ - - int viewport(int x, int y, int w, int h, - int buf_x, int buf_y, bool) override - { - /* transpose y position of top-level views by vertical session offset */ - if (_view.top_level()) - y += _view.session().v_offset(); - - _view_stack.viewport(_view, Rect(Point(x, y), Area(w, h)), - Point(buf_x, buf_y)); - return 0; - } - - int stack(Nitpicker::View_capability neighbor_cap, bool behind, bool) override - { - Object_pool::Guard nvc(_ep.lookup_and_lock(neighbor_cap)); - - ::View *neighbor_view = nvc ? &nvc->view() : 0; - - _view_stack.stack(_view, neighbor_view, behind); - return 0; - } - - int title(Title const &title) override - { - _view_stack.title(_view, title.string()); - return 0; - } -}; - - /***************************************** ** Implementation of Nitpicker service ** *****************************************/ @@ -438,7 +377,9 @@ class Nitpicker::Session_component : public Genode::Rpc_object, { private: - Genode::Allocator_guard _buffer_alloc; + typedef ::View View; + + Genode::Allocator_guard _session_alloc; Framebuffer::Session &_framebuffer; @@ -458,7 +399,9 @@ class Nitpicker::Session_component : public Genode::Rpc_object, Mode &_mode; - List _view_list; + List _view_list; + + Genode::Tslab _view_alloc { &_session_alloc }; /* capabilities for sub sessions */ Framebuffer::Session_capability _framebuffer_session_cap; @@ -469,6 +412,15 @@ class Nitpicker::Session_component : public Genode::Rpc_object, /* size of currently allocated virtual framebuffer, in bytes */ size_t _buffer_size = 0; + Attached_ram_dataspace _command_ds { env()->ram_session(), + sizeof(Command_buffer) }; + + Command_buffer &_command_buffer = *_command_ds.local_addr(); + + typedef Genode::Handle_registry View_handle_registry; + + View_handle_registry _view_handle_registry; + void _release_buffer() { if (!::Session::texture()) @@ -483,12 +435,30 @@ class Nitpicker::Session_component : public Genode::Rpc_object, ::Session::texture(0, false); ::Session::input_mask(0); - destroy(&_buffer_alloc, const_cast *>(cdt)); + destroy(&_session_alloc, const_cast *>(cdt)); - _buffer_alloc.upgrade(_buffer_size); + _session_alloc.upgrade(_buffer_size); _buffer_size = 0; } + /** + * Helper for performing sanity checks in OP_TO_FRONT and OP_TO_BACK + * + * We have to check for the equality of both the specified view and + * neighbor. If both arguments refer to the same view, the creation of + * locked pointers for both views would result in a deadlock. + */ + bool _views_are_equal(View_handle v1, View_handle v2) + { + if (!v1.valid() || !v2.valid()) + return false; + + Weak_ptr v1_ptr = _view_handle_registry.lookup(v1); + Weak_ptr v2_ptr = _view_handle_registry.lookup(v2); + + return v1_ptr == v2_ptr; + } + bool _focus_change_permitted() const { ::Session * const focused_session = _mode.focused_session(); @@ -521,6 +491,137 @@ class Nitpicker::Session_component : public Genode::Rpc_object, return strcmp(focused_label, caller_label, Genode::strlen(caller_label)) == 0; } + void _execute_command(Command const &command) + { + switch (command.opcode) { + + case Command::OP_GEOMETRY: + { + Locked_ptr view(_view_handle_registry.lookup(command.geometry.view)); + if (!view.is_valid()) + return; + + Point pos = command.geometry.rect.p1(); + + /* transpose y position of top-level views by vertical session offset */ + if (view->top_level()) + pos = pos + Point(0, v_offset()); + + if (view.is_valid()) + _view_stack.geometry(*view, Rect(pos, command.geometry.rect.area())); + + return; + } + + case Command::OP_OFFSET: + { + Locked_ptr view(_view_handle_registry.lookup(command.geometry.view)); + + if (view.is_valid()) + _view_stack.buffer_offset(*view, command.offset.offset); + + return; + } + + case Command::OP_TO_FRONT: + { + if (_views_are_equal(command.to_front.view, command.to_front.neighbor)) + return; + + Locked_ptr view(_view_handle_registry.lookup(command.to_front.view)); + if (!view.is_valid()) + return; + + /* bring to front if no neighbor is specified */ + if (!command.to_front.neighbor.valid()) { + _view_stack.stack(*view, nullptr, true); + return; + } + + /* stack view relative to neighbor */ + Locked_ptr neighbor(_view_handle_registry.lookup(command.to_front.neighbor)); + if (neighbor.is_valid()) + _view_stack.stack(*view, &(*neighbor), false); + + return; + } + + case Command::OP_TO_BACK: + { + if (_views_are_equal(command.to_front.view, command.to_front.neighbor)) + return; + + Locked_ptr view(_view_handle_registry.lookup(command.to_back.view)); + if (!view.is_valid()) + return; + + /* bring to front if no neighbor is specified */ + if (!command.to_front.neighbor.valid()) { + _view_stack.stack(*view, nullptr, false); + return; + } + + /* stack view relative to neighbor */ + Locked_ptr neighbor(_view_handle_registry.lookup(command.to_back.neighbor)); + if (neighbor.is_valid()) + _view_stack.stack(*view, &(*neighbor), true); + + return; + } + + case Command::OP_BACKGROUND: + { + if (_provides_default_bg) { + Locked_ptr view(_view_handle_registry.lookup(command.to_front.view)); + if (!view.is_valid()) + return; + + view->background(true); + _view_stack.default_background(*view); + return; + } + + /* revert old background view to normal mode */ + if (::Session::background()) + ::Session::background()->background(false); + + /* assign session background */ + Locked_ptr view(_view_handle_registry.lookup(command.to_front.view)); + if (!view.is_valid()) + return; + + ::Session::background(&(*view)); + + /* switch background view to background mode */ + if (::Session::background()) + view->background(true); + + return; + } + + case Command::OP_TITLE: + { + Locked_ptr view(_view_handle_registry.lookup(command.title.view)); + + if (view.is_valid()) + _view_stack.title(*view, command.title.title.string()); + + return; + } + + case Command::OP_NOP: + return; + } + } + + void _destroy_view(View &view) + { + _view_stack.remove_view(view); + _ep.dissolve(&view); + _view_list.remove(&view); + destroy(_view_alloc, &view); + } + public: /** @@ -534,19 +635,20 @@ class Nitpicker::Session_component : public Genode::Rpc_object, int v_offset, bool provides_default_bg, bool stay_top, - Allocator &buffer_alloc, + Allocator &session_alloc, size_t ram_quota) : ::Session(label, v_offset, stay_top), - _buffer_alloc(&buffer_alloc, ram_quota), + _session_alloc(&session_alloc, ram_quota), _framebuffer(framebuffer), _framebuffer_session_component(view_stack, *this, framebuffer, *this), _ep(ep), _view_stack(view_stack), _mode(mode), _framebuffer_session_cap(_ep.manage(&_framebuffer_session_component)), _input_session_cap(_ep.manage(&_input_session_component)), - _provides_default_bg(provides_default_bg) + _provides_default_bg(provides_default_bg), + _view_handle_registry(_session_alloc) { - _buffer_alloc.upgrade(ram_quota); + _session_alloc.upgrade(ram_quota); } /** @@ -557,13 +659,18 @@ class Nitpicker::Session_component : public Genode::Rpc_object, _ep.dissolve(&_framebuffer_session_component); _ep.dissolve(&_input_session_component); - while (View_component *vc = _view_list.first()) - destroy_view(vc->cap()); + destroy_all_views(); _release_buffer(); } - void upgrade_ram_quota(size_t ram_quota) { _buffer_alloc.upgrade(ram_quota); } + void destroy_all_views() + { + while (Session_view_list_elem *v = _view_list.first()) + _destroy_view(*static_cast(v)); + } + + void upgrade_ram_quota(size_t ram_quota) { _session_alloc.upgrade(ram_quota); } /********************************** @@ -601,61 +708,112 @@ class Nitpicker::Session_component : public Genode::Rpc_object, Input::Session_capability input_session() override { return _input_session_cap; } - View_capability create_view(View_capability parent_cap) override + View_handle create_view(View_handle parent_handle) override { - /* lookup parent view */ - View_component *parent_view = - dynamic_cast(_ep.lookup_and_lock(parent_cap)); + View *view = nullptr; /* - * FIXME: Do not allocate View meta data from Heap! - * Use a heap partition! + * Create child view */ - View_component *view = new (env()->heap()) - View_component(*this, _view_stack, _ep, - parent_view ? &parent_view->view() : 0); + if (parent_handle.valid()) { - if (parent_view) - parent_view->view().add_child(&view->view()); + try { + Locked_ptr parent(_view_handle_registry.lookup(parent_handle)); + if (!parent.is_valid()) + return View_handle(); - if (parent_view) - parent_view->release(); + view = new (_view_alloc) + View(*this, + stay_top() ? View::STAY_TOP : View::NOT_STAY_TOP, + View::NOT_TRANSPARENT, View::NOT_BACKGROUND, + &(*parent)); - _view_list.insert(view); - return _ep.manage(view); - } - - void destroy_view(View_capability view_cap) override - { - View_component *vc = dynamic_cast(_ep.lookup_and_lock(view_cap)); - if (!vc) return; - - _view_stack.remove_view(vc->view()); - _ep.dissolve(vc); - _view_list.remove(vc); - destroy(env()->heap(), vc); - } - - int background(View_capability view_cap) override - { - if (_provides_default_bg) { - Object_pool::Guard vc(_ep.lookup_and_lock(view_cap)); - vc->view().background(true); - _view_stack.default_background(vc->view()); - return 0; + parent->add_child(*view); + } + catch (View_handle_registry::Lookup_failed) { + return View_handle(); } + catch (Genode::Allocator::Out_of_memory) { + throw Nitpicker::Session::Out_of_metadata(); } } - /* revert old background view to normal mode */ - if (::Session::background()) ::Session::background()->background(false); + /* + * Create top-level view + */ + else { + try { + view = new (_view_alloc) + View(*this, + stay_top() ? View::STAY_TOP : View::NOT_STAY_TOP, + View::NOT_TRANSPARENT, View::NOT_BACKGROUND, + nullptr); + } + catch (Genode::Allocator::Out_of_memory) { + throw Nitpicker::Session::Out_of_metadata(); } + } - /* assign session background */ - Object_pool::Guard vc(_ep.lookup_and_lock(view_cap)); - ::Session::background(&vc->view()); + _view_list.insert(view); + _ep.manage(view); - /* switch background view to background mode */ - if (::Session::background()) vc->view().background(true); + return _view_handle_registry.alloc(*view); + } - return 0; + void destroy_view(View_handle handle) override + { + try { + Locked_ptr view(_view_handle_registry.lookup(handle)); + if (view.is_valid()) + _destroy_view(*view); + } + catch (View_handle_registry::Lookup_failed) { } + + _view_handle_registry.free(handle); + } + + View_handle view_handle(View_capability view_cap, View_handle handle) override + { + View *view = dynamic_cast(_ep.lookup_and_lock(view_cap)); + if (!view) return View_handle(); + + Object_pool::Guard guard(view); + + return _view_handle_registry.alloc(*view, handle); + } + + View_capability view_capability(View_handle handle) override + { + try { + Locked_ptr view(_view_handle_registry.lookup(handle)); + return view.is_valid() ? view->cap() : View_capability(); + } + catch (View_handle_registry::Lookup_failed) { + return View_capability(); + } + } + + void release_view_handle(View_handle handle) override + { + try { + _view_handle_registry.free(handle); } + + catch (View_handle_registry::Lookup_failed) { + PWRN("view lookup failed while releasing view handle"); + return; + } + } + + Genode::Dataspace_capability command_dataspace() override + { + return _command_ds.cap(); + } + + void execute() override + { + for (unsigned i = 0; i < _command_buffer.num(); i++) { + try { + _execute_command(_command_buffer.get(i)); } + catch (View_handle_registry::Lookup_failed) { + PWRN("view lookup failed during command execution"); } + } } Framebuffer::Mode mode() override @@ -671,7 +829,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object, void buffer(Framebuffer::Mode mode, bool use_alpha) override { /* check if the session quota suffices for the specified mode */ - if (_buffer_alloc.quota() < ram_quota(mode, use_alpha)) + if (_session_alloc.quota() < ram_quota(mode, use_alpha)) throw Nitpicker::Session::Out_of_metadata(); _framebuffer_session_component.notify_mode_change(mode, use_alpha); @@ -716,10 +874,10 @@ class Nitpicker::Session_component : public Genode::Rpc_object, Chunky_dataspace_texture::calc_num_bytes(size, use_alpha); Chunky_dataspace_texture * const texture = - new (&_buffer_alloc) Chunky_dataspace_texture(size, use_alpha); + new (&_session_alloc) Chunky_dataspace_texture(size, use_alpha); - if (!_buffer_alloc.withdraw(_buffer_size)) { - destroy(&_buffer_alloc, texture); + if (!_session_alloc.withdraw(_buffer_size)) { + destroy(&_session_alloc, texture); _buffer_size = 0; return 0; } @@ -756,7 +914,8 @@ class Nitpicker::Root : public Genode::Root_component bool const stay_top = Arg_string::find_arg(args, "stay_top").bool_value(false); - size_t const required_quota = Input::Session_component::ev_ds_size(); + size_t const required_quota = Input::Session_component::ev_ds_size() + + Genode::align_addr(sizeof(Session::Command_buffer), 12); if (ram_quota < required_quota) { PWRN("Insufficient dontated ram_quota (%zd bytes), require %zd bytes", @@ -791,6 +950,8 @@ class Nitpicker::Root : public Genode::Root_component { _session_list.remove(session); _global_keys.apply_config(_session_list); + + session->destroy_all_views(); _mode.forget(*session); destroy(md_alloc(), session); @@ -988,8 +1149,7 @@ void Nitpicker::Main::handle_input(unsigned) /* update mouse cursor */ if (old_mouse_pos != new_mouse_pos) - user_state.viewport(mouse_cursor, - Rect(new_mouse_pos, mouse_size), Point()); + user_state.geometry(mouse_cursor, Rect(new_mouse_pos, mouse_size)); /* perform redraw and flush pixels to the framebuffer */ user_state.draw(fb_screen->screen).flush([&] (Rect const &rect) { diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 40a66885e..666ebe963 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -93,7 +93,7 @@ void User_state::handle_event(Input::Event ev) if (type == Event::RELEASE && Mode::drag()) Mode::dec_key_cnt(); View const * const pointed_view = find_view(_mouse_pos); - Session * const pointed_session = pointed_view ? &pointed_view->session() : 0; + ::Session * const pointed_session = pointed_view ? &pointed_view->session() : 0; /* * Deliver a leave event if pointed-to session changed @@ -175,7 +175,7 @@ void User_state::handle_event(Input::Event ev) * to the global receiver. To reflect that change, we need to update * the whole screen. */ - Session * const global_receiver = _global_keys.global_receiver(keycode); + ::Session * const global_receiver = _global_keys.global_receiver(keycode); if (global_receiver) { _global_key_sequence = true; _input_receiver = global_receiver; @@ -252,7 +252,7 @@ void User_state::handle_event(Input::Event ev) ** Mode interface ** ********************/ -void User_state::forget(Session const &session) +void User_state::forget(::Session const &session) { Mode::forget(session); @@ -260,10 +260,13 @@ void User_state::forget(Session const &session) View * const pointed_view = find_view(_mouse_pos); _pointed_session = pointed_view ? &pointed_view->session() : nullptr; } + + if (_input_receiver == &session) + _input_receiver = nullptr; } -void User_state::focused_session(Session *session) +void User_state::focused_session(::Session *session) { Mode::focused_session(session); diff --git a/repos/os/src/server/nitpicker/view.h b/repos/os/src/server/nitpicker/view.h index d08f126d7..55a48a0c8 100644 --- a/repos/os/src/server/nitpicker/view.h +++ b/repos/os/src/server/nitpicker/view.h @@ -14,10 +14,14 @@ #ifndef _VIEW_H_ #define _VIEW_H_ +/* Genode includes */ #include #include #include +#include +#include +/* local includes */ #include "mode.h" #include "session.h" @@ -31,14 +35,19 @@ typedef Genode::Dirty_rect Dirty_rect; /* - * For each buffer, there is a list of views that belong to - * this buffer. This list is called Same_buffer_list. + * For each buffer, there is a list of views that belong to this buffer. */ struct Same_buffer_list_elem : Genode::List::Element { }; - +/* + * The view stack holds a list of all visible view in stacking order. + */ struct View_stack_elem : Genode::List::Element { }; +/* + * Each session maintains a list of views owned by the session. + */ +struct Session_view_list_elem : Genode::List::Element { }; /* * If a view has a parent, it is a list element of its parent view @@ -46,9 +55,22 @@ struct View_stack_elem : Genode::List::Element { }; struct View_parent_elem : Genode::List::Element { }; +namespace Nitpicker { class View; } + + +/* + * We use view capabilities as mere tokens to pass views between sessions. + * There is no RPC interface associated with a view. + */ +struct Nitpicker::View { GENODE_RPC_INTERFACE(); }; + + class View : public Same_buffer_list_elem, + public Session_view_list_elem, public View_stack_elem, - public View_parent_elem + public View_parent_elem, + public Genode::Weak_object, + public Genode::Rpc_object { public: @@ -86,11 +108,13 @@ class View : public Same_buffer_list_elem, { /* break link to our parent */ if (_parent) - _parent->remove_child(this); + _parent->remove_child(*this); /* break links to our children */ - while (View_parent_elem *e = _children.first()) + while (View_parent_elem *e = _children.first()) { static_cast(e)->dissolve_from_parent(); + _children.remove(e); + } } /** @@ -125,9 +149,9 @@ class View : public Same_buffer_list_elem, void geometry(Rect geometry) { _geometry = geometry; } - void add_child(View const *child) { _children.insert(child); } + void add_child(View const &child) { _children.insert(&child); } - void remove_child(View const *child) { _children.remove(child); } + void remove_child(View const &child) { _children.remove(&child); } template void for_each_child(FN const &fn) const { diff --git a/repos/os/src/server/nitpicker/view_stack.cc b/repos/os/src/server/nitpicker/view_stack.cc index 8fd9c4268..45cb9a3f8 100644 --- a/repos/os/src/server/nitpicker/view_stack.cc +++ b/repos/os/src/server/nitpicker/view_stack.cc @@ -237,14 +237,13 @@ void View_stack::refresh_view(View const &view, Rect const rect) } -void View_stack::viewport(View &view, Rect const rect, Point const buffer_off) +void View_stack::geometry(View &view, Rect const rect) { Rect const old_outline = _outline(view); refresh_view(view, Rect(Point(), _size)); view.geometry(Rect(rect)); - view.buffer_off(buffer_off); refresh_view(view, Rect(Point(), _size)); @@ -256,6 +255,14 @@ void View_stack::viewport(View &view, Rect const rect, Point const buffer_off) } +void View_stack::buffer_offset(View &view, Point const buffer_off) +{ + view.buffer_off(buffer_off); + + refresh_view(view, Rect(Point(), _size)); +} + + void View_stack::stack(View const &view, View const *neighbor, bool behind) { _views.remove(&view); @@ -291,6 +298,8 @@ View *View_stack::find_view(Point p) void View_stack::remove_view(View const &view, bool redraw) { + view.for_each_child([&] (View const &child) { remove_view(child); }); + /* remember geometry of view to remove */ Rect rect = _outline(view); diff --git a/repos/os/src/server/nitpicker/view_stack.h b/repos/os/src/server/nitpicker/view_stack.h index 9df9383c7..82e6562bb 100644 --- a/repos/os/src/server/nitpicker/view_stack.h +++ b/repos/os/src/server/nitpicker/view_stack.h @@ -162,12 +162,18 @@ class View_stack void refresh_view(View const &view, Rect); /** - * Define position and viewport + * Define view geometry + * + * \param rect new geometry of view on screen + */ + void geometry(View &view, Rect rect); + + /** + * Define buffer offset of view * - * \param pos position of view on screen * \param buffer_off view offset of displayed buffer */ - void viewport(View &view, Rect pos, Point buffer_off); + void buffer_offset(View &view, Point buffer_off); /** * Insert view at specified position in view stack diff --git a/repos/os/src/test/loader/main.cc b/repos/os/src/test/loader/main.cc index 1acfbf930..8bcd3c519 100644 --- a/repos/os/src/test/loader/main.cc +++ b/repos/os/src/test/loader/main.cc @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include using namespace Genode; @@ -36,16 +36,23 @@ int main(int argc, char **argv) Loader::Session::View_geometry geometry = loader.view_geometry(); Nitpicker::View_capability view_cap = loader.view(); - Nitpicker::View_client view(view_cap); - view.stack(Nitpicker::View_capability(), true, false); + static Nitpicker_connection nitpicker; + + Nitpicker::Session::View_handle view_handle = nitpicker.view_handle(view_cap); + + nitpicker.enqueue(view_handle); + nitpicker.execute(); Timer::Connection timer; while(1) { for (unsigned i = 0; i < 10; i++) { - view.viewport(50*i, 50*i, geometry.width, geometry.height, - geometry.buf_x, geometry.buf_y, true); + + Nitpicker::Rect rect(Nitpicker::Point(50*i, 50*i), + Nitpicker::Area(geometry.width, geometry.height)); + nitpicker.enqueue(rect); + timer.msleep(1000); } } diff --git a/repos/os/src/test/nitpicker/test.cc b/repos/os/src/test/nitpicker/test.cc index b674d347b..5201248da 100644 --- a/repos/os/src/test/nitpicker/test.cc +++ b/repos/os/src/test/nitpicker/test.cc @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -26,34 +25,53 @@ class Test_view : public List::Element { private: - Nitpicker::View_capability _cap; - int _x, _y, _w, _h; - const char *_title; - Test_view const *_parent_view; + typedef Nitpicker::Session::View_handle View_handle; + typedef Nitpicker::Session::Command Command; + + Nitpicker::Session_client &_nitpicker; + View_handle _handle; + int _x, _y, _w, _h; + const char *_title; + Test_view *_parent_view; public: - Test_view(Nitpicker::Session *nitpicker, + Test_view(Nitpicker::Session_client *nitpicker, int x, int y, int w, int h, const char *title, Test_view *parent_view = 0) : + _nitpicker(*nitpicker), _x(x), _y(y), _w(w), _h(h), _title(title), _parent_view(parent_view) { using namespace Nitpicker; - View_capability parent_cap = parent_view ? parent_view->_cap - : View_capability(); + View_handle parent_handle; - _cap = nitpicker->create_view(parent_cap); - View_client(_cap).viewport(_x, _y, _w, _h, 0, 0, true); - View_client(_cap).stack(Nitpicker::View_capability(), true, true); - View_client(_cap).title(_title); + if (_parent_view) + parent_handle = _nitpicker.view_handle(_parent_view->view_cap()); + + _handle = _nitpicker.create_view(parent_handle); + + if (parent_handle.valid()) + _nitpicker.release_view_handle(parent_handle); + + Nitpicker::Rect rect(Nitpicker::Point(_x, _y), Nitpicker::Area(_w, _h)); + _nitpicker.enqueue(_handle, rect); + _nitpicker.enqueue(_handle); + _nitpicker.enqueue(_handle, _title); + _nitpicker.execute(); + } + + Nitpicker::View_capability view_cap() + { + return _nitpicker.view_capability(_handle); } void top() { - Nitpicker::View_client(_cap).stack(Nitpicker::View_capability(), true, true); + _nitpicker.enqueue(_handle); + _nitpicker.execute(); } /** @@ -69,7 +87,9 @@ class Test_view : public List::Element _x = _parent_view ? x - _parent_view->x() : x; _y = _parent_view ? y - _parent_view->y() : y; - Nitpicker::View_client(_cap).viewport(_x, _y, _w, _h, 0, 0, true); + Nitpicker::Rect rect(Nitpicker::Point(_x, _y), Nitpicker::Area(_w, _h)); + _nitpicker.enqueue(_handle, rect); + _nitpicker.execute(); } /**