[Spice-devel] [PATCH] client: fix endless recursion in rearrange_monitors, RHBZ #692976

Yonit Halperin yhalperi at redhat.com
Thu Jul 21 00:49:15 PDT 2011


Hi,
forgot to mention that the endless recursion happened due to 
Application::prepare_monitors calling RedScreen::resize calling 
Application::rearrange_monitors calling Application::prepare_monitors
I will change the commit message.


On 07/21/2011 10:07 AM, Yonit Halperin wrote:
> I changed RedScreen::resize not to call rearrange_monitors. Instead,
> the monitor should be configured correctly from Application, before
> calling resize.
> In addition, I made some cleanups to allow reusing rearrange_monitors code.
> ---
>   client/application.cpp |   94 +++++++++++++++++++++++++-----------------------
>   client/application.h   |    4 ++-
>   client/screen.cpp      |    4 --
>   client/screen.h        |    2 +
>   4 files changed, 54 insertions(+), 50 deletions(-)
>
> diff --git a/client/application.cpp b/client/application.cpp
> index f19bd58..ce91b2a 100644
> --- a/client/application.cpp
> +++ b/client/application.cpp
> @@ -664,25 +664,9 @@ RedScreen* Application::get_screen(int id)
>
>           if (id != 0) {
>               if (_full_screen) {
> -                bool capture;
> -
>                   mon = get_monitor(id);
> -                capture = release_capture();
>                   screen->set_monitor(mon);
> -                prepare_monitors();
> -                position_screens();
> -                screen->show_full_screen();
> -                if (screen->is_out_of_sync()) {
> -                    _out_of_sync = true;
> -                    /* If the client monitor cannot handle the guest resolution
> -                       drop back to windowed mode */
> -                    exit_full_screen();
> -                }
> -
> -                if (capture) {
> -                    _main_screen->activate();
> -                    _main_screen->capture_mouse();
> -                }
> +                rearrange_monitors(false, true, screen);
>               } else {
>                   screen->show(false, _main_screen);
>               }
> @@ -770,13 +754,7 @@ void Application::on_screen_destroyed(int id, bool was_captured)
>       }
>       _screens[id] = NULL;
>       if (reposition) {
> -        bool capture = was_captured || release_capture();
> -        prepare_monitors();
> -        position_screens();
> -        if (capture) {
> -            _main_screen->activate();
> -            _main_screen->capture_mouse();
> -        }
> +        rearrange_monitors(was_captured, false);
>       }
>   }
>
> @@ -1387,20 +1365,51 @@ void Application::on_screen_unlocked(RedScreen&  screen)
>       screen.resize(SCREEN_INIT_WIDTH, SCREEN_INIT_HEIGHT);
>   }
>
> -bool Application::rearrange_monitors(RedScreen&  screen)
> +void Application::rearrange_monitors(bool force_capture,
> +                                     bool enter_full_screen,
> +                                     RedScreen* screen)
>   {
> -    if (!_full_screen) {
> -        return false;
> +    bool capture;
> +    bool toggle_full_screen;
> +
> +    if (!_full_screen&&  !enter_full_screen) {
> +        return;
> +    }
> +
> +    toggle_full_screen = enter_full_screen&&  !screen;
> +    capture = release_capture();
> +#ifndef WIN32
> +    if (toggle_full_screen) {
> +        /* performing hide during resolution changes resulted in
> +           missing WM_KEYUP events */
> +        hide();
>       }
> -    bool capture = release_capture();
> +#endif
>       prepare_monitors();
>       position_screens();
> -    if (capture&&  _main_screen !=&screen) {
> -        capture = false;
> -        _main_screen->activate();
> +    if (enter_full_screen) {
> +        // toggling to full screen
> +        if (toggle_full_screen) {
> +            show_full_screen();
> +            _main_screen->activate();
> +
> +        } else { // already in full screen mode and a new screen is displayed
> +            screen->show_full_screen();
> +            if (screen->is_out_of_sync()) {
> +                _out_of_sync = true;
> +                /* If the client monitor cannot handle the guest resolution
> +                    drop back to windowed mode */
> +                exit_full_screen();
> +            }
> +        }
> +    }
> +
> +    if (force_capture || capture) {
> +        if (!toggle_full_screen) {
> +            _main_screen->activate();
> +        }
>           _main_screen->capture_mouse();
>       }
> -    return capture;
>   }
>
>   Monitor* Application::find_monitor(int id)
> @@ -1517,20 +1526,8 @@ void Application::enter_full_screen()
>   {
>       LOG_INFO("");
>       _changing_screens = true;
> -    bool capture = release_capture();
>       assign_monitors();
> -#ifndef WIN32
> -    /* performing hide during resolution changes resulted in
> -       missing WM_KEYUP events */
> -    hide();
> -#endif
> -    prepare_monitors();
> -    position_screens();
> -    show_full_screen();
> -    _main_screen->activate();
> -    if (capture) {
> -        _main_screen->capture_mouse();
> -    }
> +    rearrange_monitors(false, true);
>       _changing_screens = false;
>       _full_screen = true;
>       /* If the client monitor cannot handle the guest resolution drop back
> @@ -1592,7 +1589,14 @@ bool Application::toggle_full_screen()
>
>   void Application::resize_screen(RedScreen *screen, int width, int height)
>   {
> +    Monitor* mon;
> +    if (_full_screen) {
> +        if ((mon = screen->get_monitor())) {
> +            mon->set_mode(width, height);
> +        }
> +    }
>       screen->resize(width, height);
> +    rearrange_monitors(false, false);
>       if (screen->is_out_of_sync()) {
>           _out_of_sync = true;
>           /* If the client monitor cannot handle the guest resolution
> diff --git a/client/application.h b/client/application.h
> index 4133dfe..8079753 100644
> --- a/client/application.h
> +++ b/client/application.h
> @@ -216,7 +216,6 @@ public:
>       void on_disconnecting();
>       void on_visibility_start(int screen_id);
>
> -    bool rearrange_monitors(RedScreen&  screen);
>       void enter_full_screen();
>       void exit_full_screen();
>       bool toggle_full_screen();
> @@ -308,6 +307,9 @@ private:
>       void assign_monitors();
>       void restore_monitors();
>       void prepare_monitors();
> +    void rearrange_monitors(bool force_capture,
> +                            bool enter_full_screen,
> +                            RedScreen* screen = NULL);
>       void position_screens();
>       void show_full_screen();
>       void send_key_down(RedKey key);
> diff --git a/client/screen.cpp b/client/screen.cpp
> index caa5d4f..e085781 100644
> --- a/client/screen.cpp
> +++ b/client/screen.cpp
> @@ -186,11 +186,7 @@ void RedScreen::resize(int width, int height)
>       _size.y = height;
>       create_composit_area();
>       if (_full_screen) {
> -        bool cuptur = _owner.rearrange_monitors(*this);
>           __show_full_screen();
> -        if (cuptur) {
> -            capture_mouse();
> -        }
>       } else {
>           bool cuptur = is_mouse_captured();
>           if (cuptur) {
> diff --git a/client/screen.h b/client/screen.h
> index 2b40d77..e7db4ef 100644
> --- a/client/screen.h
> +++ b/client/screen.h
> @@ -62,6 +62,8 @@ public:
>       void attach_layer(ScreenLayer&  layer);
>       void detach_layer(ScreenLayer&  layer);
>       void on_layer_changed(ScreenLayer&  layer);
> +    /* When resizing on full screen mode, the monitor must be configured
> +     * correctly before calling resize*/
>       void resize(int width, int height);
>       void set_name(const std::string&  name);
>       uint64_t invalidate(const SpiceRect&  rect, bool urgent);



More information about the Spice-devel mailing list