From 314d5c09752c0b5121eb2587e79399d2459d3f36 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Wed, 22 May 2013 19:21:29 +0200 Subject: [PATCH] liquid_fb: dynamic reconfiguration support With this patch, 'liquid_framebuffer' can be reconfigured at runtime. The configuration arguments are now provided as XML attributes, matching those for 'nit_fb'. Furthermore, two new configuration options are added: Fixes #740 Fixes #14 --- demo/src/app/scout/genode/platform_genode.cc | 28 ++- demo/src/app/scout/include/platform.h | 5 +- demo/src/app/scout/include/user_state.h | 15 +- demo/src/app/scout/include/window.h | 2 +- demo/src/server/liquid_framebuffer/README | 26 ++- .../liquid_framebuffer/framebuffer_window.h | 90 +++++++- demo/src/server/liquid_framebuffer/main.cc | 210 ++++++++++++++---- .../src/server/liquid_framebuffer/services.cc | 50 +---- demo/src/server/liquid_framebuffer/services.h | 5 +- ports-foc/run/multi_linux.run | 9 +- ports/run/vancouver.run | 7 +- 11 files changed, 313 insertions(+), 134 deletions(-) diff --git a/demo/src/app/scout/genode/platform_genode.cc b/demo/src/app/scout/genode/platform_genode.cc index 7a97a8eca..b57989239 100644 --- a/demo/src/app/scout/genode/platform_genode.cc +++ b/demo/src/app/scout/genode/platform_genode.cc @@ -39,7 +39,7 @@ static Timer::Session *_timer; static unsigned long _timer_tick; static int _init_flag; static bool _view_initialized; -static int _vx, _vy, _vw, _vh; /* view geometry */ +static int _vx, _vy, _vw, _vh, _vbx, _vby; /* view geometry */ /** @@ -52,7 +52,8 @@ static Nitpicker::View_capability create_and_top_view() { Nitpicker::View_capability cap = _nitpicker->create_view(); Nitpicker::View_client(cap).stack(Nitpicker::View_capability(), true, true); - Nitpicker::View_client(cap).viewport(_vx, _vy, _vw, _vh, 0, _flip_state ? -_scr_h : 0, true); + Nitpicker::View_client(cap).viewport(_vx - _vbx, _vy - _vby, _vw, _vh, + _vbx, _flip_state ? _vby - _scr_h : _vby, true); return cap; } @@ -208,7 +209,7 @@ Platform::Platform(unsigned vx, unsigned vy, unsigned vw, unsigned vh, unsigned max_vw, unsigned max_vh) : _max_vw(max_vw), _max_vh(max_vh) { - _vx = vx, _vy = vy, _vw = vw, _vh = vh; + _vx = vx, _vy = vy, _vw = vw, _vh = vh, _vbx = 0, _vby = 0; Config::mouse_cursor = 0; Config::browser_attr = 7; @@ -284,7 +285,7 @@ void Platform::flip_buf_scr() _flip_state ^= 1; /* enable new foreground buffer by configuring the view port */ - view_geometry(_vx, _vy, _vw, _vh); + view_geometry(_vx, _vy, _vw, _vh, false, _vbx, _vby); } @@ -344,18 +345,23 @@ void Platform::top_view() /** * Report view geometry changes to Nitpicker. */ -void Platform::view_geometry(int x, int y, int w, int h, int do_redraw) +void Platform::view_geometry(int x, int y, int w, int h, int do_redraw, + int buf_x, int buf_y) { - _vx = x; _vy = y; _vw = w; _vh = h; + _vx = x; _vy = y; _vw = w; _vh = h; _vbx = buf_x, _vby = buf_y; if (_view_initialized) - view()->viewport(_vx, _vy, _vw, _vh, 0, _flip_state ? -_scr_h : 0, do_redraw); + view()->viewport(_vx - _vbx, _vy - _vby, _vw, _vh, + _vbx, + _flip_state ? _vby - _scr_h : _vby, do_redraw); } -int Platform::vx() { return _vx; } -int Platform::vy() { return _vy; } -int Platform::vw() { return _vw; } -int Platform::vh() { return _vh; } +int Platform::vx() { return _vx; } +int Platform::vy() { return _vy; } +int Platform::vw() { return _vw; } +int Platform::vh() { return _vh; } +int Platform::vbx() { return _vbx; } +int Platform::vby() { return _vby; } /** diff --git a/demo/src/app/scout/include/platform.h b/demo/src/app/scout/include/platform.h index 47b96341f..c86835c6a 100644 --- a/demo/src/app/scout/include/platform.h +++ b/demo/src/app/scout/include/platform.h @@ -109,7 +109,8 @@ class Platform : public Screen_update * The specified area is relative to the screen * of the platform. */ - void view_geometry(int x, int y, int w, int h, int do_redraw = 0); + void view_geometry(int x, int y, int w, int h, int do_redraw = 0, + int buf_x = 0, int buf_y = 0); /** * Bring Scouts view ontop @@ -123,6 +124,8 @@ class Platform : public Screen_update int vy(); int vw(); int vh(); + int vbx(); + int vby(); /** * Get timer ticks in miilliseconds diff --git a/demo/src/app/scout/include/user_state.h b/demo/src/app/scout/include/user_state.h index 7a0de2df9..22fc196f0 100644 --- a/demo/src/app/scout/include/user_state.h +++ b/demo/src/app/scout/include/user_state.h @@ -84,6 +84,15 @@ class User_state : public Parent_element int vx() { return _vx; } int vy() { return _vy; } + /** + * Update the current view offset + */ + void update_view_offset() + { + _vx = _window->view_x(); + _vy = _window->view_y(); + } + /** * Apply input event to mouse focus state */ @@ -112,8 +121,7 @@ class User_state : public Parent_element _active = e; _active->handle_event(ev); - _vx = _window->view_x(); - _vy = _window->view_y(); + update_view_offset(); _assign_mfocus(_root->find(ev.mx, ev.my), 1); @@ -122,8 +130,7 @@ class User_state : public Parent_element case Event::RELEASE: if (_key_cnt == 0) { - _vx = _window->view_x(); - _vy = _window->view_y(); + update_view_offset(); _active = 0; _assign_mfocus(e); } diff --git a/demo/src/app/scout/include/window.h b/demo/src/app/scout/include/window.h index a35edbe78..383fdd8b9 100644 --- a/demo/src/app/scout/include/window.h +++ b/demo/src/app/scout/include/window.h @@ -71,7 +71,7 @@ class Window : public Parent_element * Move window to new position */ virtual void vpos(int x, int y) { - _pf->view_geometry(x, y, _pf->vw(), _pf->vh(), 1); } + _pf->view_geometry(x, y, _pf->vw(), _pf->vh(), 1, _pf->vbx(), _pf->vby()); } /** * Define vertical scroll offset diff --git a/demo/src/server/liquid_framebuffer/README b/demo/src/server/liquid_framebuffer/README index 43b620287..b66313f88 100644 --- a/demo/src/server/liquid_framebuffer/README +++ b/demo/src/server/liquid_framebuffer/README @@ -3,23 +3,31 @@ running as a client of the Nitpicker GUI server. It supports the following configuration options. The example shows the default values. -! +! -! on +! valid values are 'on' and 'off' --> +! animate="on" ! ! -! 400 -! 270 -! 500 -! 400 +! xpos="400" +! ypos="270" +! width="500" +! height="400" ! ! -! Liquid Framebuffer +! title="Liquid Framebuffer" ! -! +! +! resize_handle="off" +! +! +! decoration="on" +! +! /> Because Liquid frame buffer creates the virtual frame-buffer window at start time, not at session-creation time, sufficient memory resources must diff --git a/demo/src/server/liquid_framebuffer/framebuffer_window.h b/demo/src/server/liquid_framebuffer/framebuffer_window.h index 96e22eb6e..2f2f4e908 100644 --- a/demo/src/server/liquid_framebuffer/framebuffer_window.h +++ b/demo/src/server/liquid_framebuffer/framebuffer_window.h @@ -45,6 +45,8 @@ class Framebuffer_window : public Window Fade_icon _sizer; Element *_content; bool _config_alpha; + bool _config_resize_handle; + bool _config_decoration; public: @@ -55,10 +57,14 @@ class Framebuffer_window : public Window Redraw_manager *redraw, Element *content, const char *name, - bool config_alpha) + bool config_alpha, + bool config_resize_handle, + bool config_decoration) : Window(pf, redraw, content->min_w() + 2, content->min_h() + 1 + _TH), - _bg_offset(0), _content(content) + _bg_offset(0), _content(content), _config_alpha(config_alpha), + _config_resize_handle(config_resize_handle), + _config_decoration(config_decoration) { /* titlebar */ _titlebar.rgba(TITLEBAR_RGBA); @@ -70,12 +76,71 @@ class Framebuffer_window : public Window _sizer.event_handler(new Sizer_event_handler(this)); _sizer.alpha(100); - append(&_titlebar); - append(_content); - append(&_sizer); + if (config_decoration) + append(&_titlebar); - _min_w = max_w(); - _min_h = max_h(); + append(_content); + + if (config_resize_handle) + append(&_sizer); + + _min_w = 1 + 32 + 1; /* left border + resize handle + right border */ + _min_h = _TH + 32 + 1; /* title bar + resize handle + bottom border */ + } + + /** + * Set the window title + */ + void name(const char *name) + { + _titlebar.text(name); + } + + /** + * Set the alpha config option + */ + void config_alpha(bool alpha) + { + _config_alpha = alpha; + } + + /** + * Set the resize_handle config option + */ + void config_resize_handle(bool resize_handle) + { + if (!_config_resize_handle && resize_handle) + append(&_sizer); + else if (_config_resize_handle && !resize_handle) + remove(&_sizer); + + _config_resize_handle = resize_handle; + } + + /** + * Set the decoration config option + */ + void config_decoration(bool decoration) + { + _config_decoration = decoration; + } + + /** + * Move window to new position + */ + void vpos(int x, int y) + { + Window::vpos(x, y); + format(_w, _h); + } + + /** + * Resize the window according to the new content size + */ + void content_geometry(int x, int y, int w, int h) + { + Window::vpos(x, y); + format(w + 2, h + 1 + _TH); } /** @@ -83,6 +148,9 @@ class Framebuffer_window : public Window */ void format(int w, int h) { + /* limit window size to valid values */ + w = (w < _min_w) ? _min_w : w; + h = (h < _min_h) ? _min_h : h; w = (w > max_w()) ? max_w() : w; h = (h > max_h()) ? max_h() : h; _w = w; @@ -101,7 +169,13 @@ class Framebuffer_window : public Window _sizer.geometry(_w - 32, _h - 32, 32, 32); - pf()->view_geometry(pf()->vx(), pf()->vy(), _w, _h); + pf()->top_view(); + + if (_config_decoration) + pf()->view_geometry(pf()->vx(), pf()->vy(), _w, _h); + else + pf()->view_geometry(pf()->vx(), pf()->vy(), + _w - 2, _h - 1 - _TH, false, -1, -_TH); redraw()->size(_w, _h); refresh(); } diff --git a/demo/src/server/liquid_framebuffer/main.cc b/demo/src/server/liquid_framebuffer/main.cc index dfba4be63..4dde79814 100644 --- a/demo/src/server/liquid_framebuffer/main.cc +++ b/demo/src/server/liquid_framebuffer/main.cc @@ -11,6 +11,9 @@ * under the terms of the GNU General Public License version 2. */ +#include +#include +#include #include #include "framebuffer_window.h" @@ -18,6 +21,8 @@ #include "user_state.h" #include "services.h" +using namespace Genode; + /** * Runtime configuration */ @@ -85,6 +90,15 @@ static long config_fb_y = 260; */ static const char *config_title = "Liquid Framebuffer"; +/** + * Resize handle + */ +static bool config_resize_handle = false; + +/** + * Window decoration + */ +static bool config_decoration = true; /** * Parse configuration @@ -97,37 +111,150 @@ static void read_config() try { char buf[16]; - config_node.sub_node("animate").value(buf, sizeof(buf)); + config_node.attribute("animate").value(buf, sizeof(buf)); if (!strcmp("off", buf)) config_animate = false; else if (!strcmp("on", buf)) config_animate = true; else Genode::printf("Warning: invalid value for animate declaration,\n" " valid values are 'on', 'off.\n'"); - } catch (Xml_node::Nonexistent_sub_node) { } + } catch (Xml_node::Nonexistent_attribute) { } config_alpha = config_animate; - try { config_node.sub_node("x").value(&config_fb_x); } - catch (Xml_node::Nonexistent_sub_node) { } + try { config_node.attribute("xpos").value(&config_fb_x); } + catch (Xml_node::Nonexistent_attribute) { } - try { config_node.sub_node("y").value(&config_fb_y); } - catch (Xml_node::Nonexistent_sub_node) { } + try { config_node.attribute("ypos").value(&config_fb_y); } + catch (Xml_node::Nonexistent_attribute) { } - try { config_node.sub_node("width").value(&config_fb_width); } - catch (Xml_node::Nonexistent_sub_node) { } + try { config_node.attribute("width").value(&config_fb_width); } + catch (Xml_node::Nonexistent_attribute) { } - try { config_node.sub_node("height").value(&config_fb_height); } - catch (Xml_node::Nonexistent_sub_node) { } + try { config_node.attribute("height").value(&config_fb_height); } + catch (Xml_node::Nonexistent_attribute) { } try { static char buf[64]; - config_node.sub_node("title").value(buf, sizeof(buf)); + config_node.attribute("title").value(buf, sizeof(buf)); config_title = buf; - } catch (Xml_node::Nonexistent_sub_node) { } + } catch (Xml_node::Nonexistent_attribute) { } + + try { + char buf[16]; + config_node.attribute("decoration").value(buf, sizeof(buf)); + + if (!strcmp("off", buf)) config_decoration = false; + else if (!strcmp("on", buf)) config_decoration = true; + else + Genode::printf("Warning: invalid value for decoration declaration,\n" + " valid values are 'on', 'off.\n'"); + } catch (Xml_node::Nonexistent_attribute) { } + + try { + char buf[16]; + config_node.attribute("resize_handle").value(buf, sizeof(buf)); + + if (!strcmp("off", buf)) config_resize_handle = false; + else if (!strcmp("on", buf)) config_resize_handle = true; + else + Genode::printf("Warning: invalid value for resize_handle declaration,\n" + " valid values are 'on', 'off.\n'"); + } catch (Xml_node::Nonexistent_attribute) { } + } +/******************* + ** Input handler ** + *******************/ + +struct Input_handler +{ + GENODE_RPC(Rpc_handle_input, void, handle, Event&); + GENODE_RPC_INTERFACE(Rpc_handle_input); +}; + + +class Input_handler_component : public Genode::Rpc_object +{ + + private: + + Platform &_pf; + User_state &_user_state; + Framebuffer_window &_fb_win; + Redraw_manager &_redraw; + Signal_receiver &_sig_rec; + unsigned long _curr_time, _old_time; + + public: + + Input_handler_component(Platform &pf, + User_state &user_state, + Framebuffer_window &fb_win, + Redraw_manager &redraw, + Signal_receiver &sig_rec) + : _pf(pf), + _user_state(user_state), + _fb_win(fb_win), + _redraw(redraw), + _sig_rec(sig_rec) + { + _curr_time = _old_time = _pf.timer_ticks(); + } + + void handle(Event &ev) + { + if (ev.type != Event::WHEEL) { + ev.mx -= _user_state.vx(); + ev.my -= _user_state.vy(); + } + + /* direct all keyboard events to the window content */ + if ((ev.type == Event::PRESS || ev.type == Event::RELEASE) + && (ev.code != Event::BTN_LEFT)) + window_content()->handle_event(ev); + else + _user_state.handle_event(ev); + + if (ev.type == Event::REFRESH) + _pf.scr_update(0, 0, _pf.scr_w(), _pf.scr_h()); + + if (ev.type == Event::TIMER) { + Tick::handle(_pf.timer_ticks()); + /* check for configuration changes */ + if (_sig_rec.pending()) { + _sig_rec.wait_for_signal(); + config()->reload(); + /* keep the current values by default */ + config_fb_x = _fb_win.view_x(); + config_fb_y = _fb_win.view_y(); + config_fb_width = _fb_win.view_w(); + config_fb_height = _fb_win.view_h(); + try { read_config(); } catch (...) { } + _fb_win.name(config_title); + _fb_win.config_alpha(config_alpha); + _fb_win.config_resize_handle(config_resize_handle); + _fb_win.config_decoration(config_decoration); + /* must get called after 'config_decoration()' */ + _fb_win.content_geometry(config_fb_x, config_fb_y, + config_fb_width, config_fb_height); + _user_state.update_view_offset(); + } + } + + /* perform periodic redraw */ + _curr_time = _pf.timer_ticks(); + if (!_pf.event_pending() && ((_curr_time - _old_time > 20) || (_curr_time < _old_time))) { + _old_time = _curr_time; + _redraw.process(); + } + } +}; + + /** * Main program */ @@ -137,6 +264,14 @@ int main(int argc, char **argv) try { read_config(); } catch (...) { } + /* + * Register signal handler for config changes + */ + static Signal_receiver sig_rec; + static Signal_context sig_ctx; + + try { config()->sigh(sig_rec.manage(&sig_ctx)); } catch (...) { } + /* heuristic for allocating the double-buffer backing store */ enum { WINBORDER_WIDTH = 10, WINBORDER_HEIGHT = 40 }; @@ -147,8 +282,8 @@ int main(int argc, char **argv) config_fb_width + WINBORDER_WIDTH, config_fb_height + WINBORDER_HEIGHT); - /* initialize our services and window content */ - init_services(config_fb_width, config_fb_height, config_alpha); + /* initialize our window content */ + init_window_content(config_fb_width, config_fb_height, config_alpha); /* init canvas */ static Chunky_canvas canvas; @@ -162,7 +297,8 @@ int main(int argc, char **argv) /* create instance of browser window */ static Framebuffer_window - fb_win(&pf, &redraw, window_content(), config_title, config_alpha); + fb_win(&pf, &redraw, window_content(), config_title, config_alpha, + config_resize_handle, config_decoration); if (config_animate) { static Background_animator fb_win_bg_anim(&fb_win); @@ -177,40 +313,24 @@ int main(int argc, char **argv) fb_win.parent(&user_state); fb_win.format(fb_win.min_w(), fb_win.min_h()); + /* initialize server entry point */ + enum { STACK_SIZE = 2*1024*sizeof(addr_t) }; + static Cap_connection cap; + static Rpc_entrypoint ep(&cap, STACK_SIZE, "liquid_fb_ep"); + + /* initialize public services */ + init_services(ep); + + /* create local input handler service */ + static Input_handler_component input_handler(pf, user_state, fb_win, + redraw, sig_rec); + Capability input_handler_cap = ep.manage(&input_handler); + /* enter main loop */ Event ev; - unsigned long curr_time, old_time; - curr_time = old_time = pf.timer_ticks(); - lock_window_content(); do { - unlock_window_content(); pf.get_event(&ev); - lock_window_content(); - - if (ev.type != Event::WHEEL) { - ev.mx -= user_state.vx(); - ev.my -= user_state.vy(); - } - - /* direct all keyboard events to the window content */ - if ((ev.type == Event::PRESS || ev.type == Event::RELEASE) - && (ev.code != Event::BTN_LEFT)) - window_content()->handle_event(ev); - else - user_state.handle_event(ev); - - if (ev.type == Event::REFRESH) - pf.scr_update(0, 0, pf.scr_w(), pf.scr_h()); - - if (ev.type == Event::TIMER) - Tick::handle(pf.timer_ticks()); - - /* perform periodic redraw */ - curr_time = pf.timer_ticks(); - if (!pf.event_pending() && ((curr_time - old_time > 20) || (curr_time < old_time))) { - old_time = curr_time; - redraw.process(); - } + input_handler_cap.call(ev); } while (ev.type != Event::QUIT); return 0; diff --git a/demo/src/server/liquid_framebuffer/services.cc b/demo/src/server/liquid_framebuffer/services.cc index 49a7c5081..28d9ac78f 100644 --- a/demo/src/server/liquid_framebuffer/services.cc +++ b/demo/src/server/liquid_framebuffer/services.cc @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -90,21 +89,16 @@ class Window_content : public Element { private: - Genode::Lock &_lock; Event_queue *_ev_queue; int _omx, _omy; Element *_element; public: - Content_event_handler(Event_queue *ev_queue, Element *element, - Genode::Lock &lock) + Content_event_handler(Event_queue *ev_queue, Element *element) : - _lock(lock), _ev_queue(ev_queue), _element(element) { } + _ev_queue(ev_queue), _element(element) { } - /* - * Called from main program with taken lock for window content - */ void handle(Event &ev) { int mx = ev.mx - _element->abs_x(); @@ -171,7 +165,6 @@ class Window_content : public Element }; - Genode::Lock _lock; bool _config_alpha; Content_event_handler _ev_handler; Fb_texture *_fb; @@ -185,7 +178,7 @@ class Window_content : public Element bool config_alpha) : _config_alpha(config_alpha), - _ev_handler(ev_queue, this, _lock), + _ev_handler(ev_queue, this), _fb(new (Genode::env()->heap()) Fb_texture(fb_w, fb_h, _config_alpha)), _new_w(fb_w), _new_h(fb_h), _wait_for_refresh(false) @@ -196,35 +189,24 @@ class Window_content : public Element event_handler(&_ev_handler); } - /* - * Accessors, called by the RPC entrypoint. Hence, the need for - * locking. - */ - Genode::Dataspace_capability fb_ds_cap() { - Genode::Lock::Guard guard(_lock); return _fb->ds.cap(); } unsigned fb_w() { - Genode::Lock::Guard guard(_lock); return _fb->w; } unsigned fb_h() { - Genode::Lock::Guard guard(_lock); return _fb->h; } void mode_sigh(Genode::Signal_context_capability sigh) { - Genode::Lock::Guard guard(_lock); _mode_sigh = sigh; } void realloc_framebuffer() { - Genode::Lock::Guard guard(_lock); - /* skip reallocation if size has not changed */ if (_new_w == _fb->w && _new_h == _fb->h) return; @@ -246,9 +228,6 @@ class Window_content : public Element /** * Element interface - * - * Called indirectly by the Content_event_handler thread, which has - * already taken the lock. */ void draw(Canvas *c, int x, int y) { @@ -264,9 +243,6 @@ class Window_content : public Element if (_mode_sigh.valid()) Genode::Signal_transmitter(_mode_sigh).submit(); } - - void lock() { _lock.lock(); } - void unlock() { _lock.unlock(); } }; @@ -274,9 +250,6 @@ static Window_content *_window_content; Element *window_content() { return _window_content; } -void lock_window_content() { _window_content->lock(); } -void unlock_window_content() { _window_content->unlock(); } - /*********************************************** ** Implementation of the framebuffer service ** @@ -342,24 +315,21 @@ namespace Framebuffer } -void init_services(unsigned fb_w, unsigned fb_h, bool config_alpha) +void init_window_content(unsigned fb_w, unsigned fb_h, bool config_alpha) { - using namespace Genode; - static Window_content content(fb_w, fb_h, &_ev_queue, config_alpha); _window_content = &content; +} - /* - * Initialize server entry point - */ - enum { STACK_SIZE = 4096 }; - static Cap_connection cap; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "liquid_fb_ep"); + +void init_services(Genode::Rpc_entrypoint &ep) +{ + using namespace Genode; /* * Let the entry point serve the framebuffer and input root interfaces */ - static Framebuffer::Root fb_root(&ep, env()->heap(), content); + static Framebuffer::Root fb_root(&ep, env()->heap(), *_window_content); static Input::Root input_root(&ep, env()->heap()); /* diff --git a/demo/src/server/liquid_framebuffer/services.h b/demo/src/server/liquid_framebuffer/services.h index 94e075314..8141e8d4b 100644 --- a/demo/src/server/liquid_framebuffer/services.h +++ b/demo/src/server/liquid_framebuffer/services.h @@ -14,11 +14,14 @@ #ifndef _SERVICES_H_ #define _SERVICES_H_ +#include + #include "canvas.h" #include "elements.h" extern Element *window_content(); -extern void init_services(unsigned fb_w, unsigned fb_h, bool config_alpha); +extern void init_window_content(unsigned fb_w, unsigned fb_h, bool config_alpha); +extern void init_services(Genode::Rpc_entrypoint &ep); extern void lock_window_content(); extern void unlock_window_content(); diff --git a/ports-foc/run/multi_linux.run b/ports-foc/run/multi_linux.run index 0e3ce92da..c40afa145 100644 --- a/ports-foc/run/multi_linux.run +++ b/ports-foc/run/multi_linux.run @@ -106,14 +106,7 @@ append config { - - off - 400 - 270 - 300 - 200 - Linux - + diff --git a/ports/run/vancouver.run b/ports/run/vancouver.run index 32a3c88e4..7b1397a5e 100644 --- a/ports/run/vancouver.run +++ b/ports/run/vancouver.run @@ -114,12 +114,7 @@ puts $launchpad_cfg_fd { - - off - 1010 - 800 - 600 - +