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

Yonit Halperin yhalperi at redhat.com
Thu Jul 21 00:07:57 PDT 2011


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);
-- 
1.7.4.4



More information about the Spice-devel mailing list