[Spice-commits] 5 commits - client/application.cpp client/red_client.cpp client/x11

Hans de Goede jwrdegoede at kemper.freedesktop.org
Mon Oct 18 01:52:11 PDT 2010


 client/application.cpp    |    4 +-
 client/red_client.cpp     |   13 ++-------
 client/x11/platform.cpp   |   10 +++++++
 client/x11/red_window.cpp |   62 ++++++++++++++++++++++++++++++++--------------
 client/x11/red_window_p.h |   10 +++++--
 5 files changed, 67 insertions(+), 32 deletions(-)

New commits:
commit d08b8120d64cf39035b59b8a8f34319d3b65b47e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Oct 17 14:55:15 2010 +0200

    spicec-x11: Fix window management under KDE
    
    There were 2 issues with window management under KDE
    1) When an app does its own focus management like we do, kwin expects
       an explicit raise for the app to get to the top, so we did have focus,
       but would have other windows (partially) covering the client window
       -> do a raise after setting focus to ourselves
    2) When switching from fullscreen <-> window, we unmap and remap our
       window, then set focus to ourselves. kwin thinks this means we're trying
       to steal the focus without the user asking for it. This patch makes us
       set the _NET_WM_USER_TIME property on our window, this helps kwin's
       focus stealing code to see that we are really not stealing the focus,
       just responding to a user event.

diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index 8f6535b..7cdf684 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -801,6 +801,10 @@ void RedWindow_p::win_proc(XEvent& event)
     }
     case KeyPress:
         red_window->handle_key_press_event(*red_window, &event.xkey);
+        red_window->last_event_time = event.xkey.time;
+        XChangeProperty(x_display, red_window->_win, wm_user_time,
+                        XA_CARDINAL, 32, PropModeReplace,
+                        (unsigned char *)&event.xkey.time, 1);
         break;
     case KeyRelease: {
         RedKey key = to_red_key_code(event.xkey.keycode);
@@ -829,6 +833,10 @@ void RedWindow_p::win_proc(XEvent& event)
             break;
         }
         red_window->get_listener().on_mouse_button_press(button, state);
+        red_window->last_event_time = event.xkey.time;
+        XChangeProperty(x_display, red_window->_win, wm_user_time,
+                        XA_CARDINAL, 32, PropModeReplace,
+                        (unsigned char *)&event.xbutton.time, 1);
         break;
     }
     case ButtonRelease: {
@@ -1526,6 +1534,8 @@ void RedWindow::show(int screen_id)
         XDeleteProperty(x_display, _win, wm_state);
         wait_parent = true;
     }
+    XChangeProperty(x_display, _win, wm_user_time, XA_CARDINAL, 32,
+                    PropModeReplace, (unsigned char *)&last_event_time, 1);
     XMapWindow(x_display, _win);
     move_to_current_desktop();
     _expect_parent = wait_parent;
@@ -1664,6 +1674,8 @@ void RedWindow::activate()
 {
     //todo: use _NET_ACTIVE_WINDOW
     XSetInputFocus(x_display, _win, RevertToParent, CurrentTime);
+    /* kwin won't raise on focus */
+    XRaiseWindow(x_display, _win);
 }
 
 void RedWindow::minimize()
diff --git a/client/x11/red_window_p.h b/client/x11/red_window_p.h
index 8f14d4e..4ad5451 100644
--- a/client/x11/red_window_p.h
+++ b/client/x11/red_window_p.h
@@ -82,6 +82,7 @@ protected:
     RedWindow *_red_window;
     int _width;
     int _height;
+    Time last_event_time;
 };
 
 #endif
commit 421ddb7422d676c5bd15f1434203aa6f3b8dc170
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Oct 17 11:38:08 2010 +0200

    client: change monitor mode setting <-> fullscreen window mode setting order
    
    1) Make the order when starting up in fullscreen mode the same as when
       switching from window -> fullscreen:
       First set the mode, then make the window fullscreen
    2) Change the order when leaving fullscreen mode, first restore the original
       monitor mode, then make the window non fullscreen. Changing the monitor
       mode in X11 causes the window manager to re-arrange windows, and if this
       happens while compiz is busy mapping the window it gets confused and
       maps the window with a maxmimized size.

diff --git a/client/application.cpp b/client/application.cpp
index 3aaa3e3..15916f7 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -673,9 +673,9 @@ RedScreen* Application::get_screen(int id)
                 mon = get_monitor(id);
                 capture = release_capture();
                 screen->set_monitor(mon);
+                prepare_monitors();
                 position_screens();
                 screen->show_full_screen();
-                prepare_monitors();
 
                 if (capture) {
                     _main_screen->activate();
@@ -1529,6 +1529,7 @@ void Application::exit_full_screen()
     LOG_INFO("");
     _changing_screens = true;
     release_capture();
+    restore_monitors();
     for (int i = 0; i < (int)_screens.size(); i++) {
         if (_screens[i]) {
             Monitor* mon;
@@ -1539,7 +1540,6 @@ void Application::exit_full_screen()
             }
         }
     }
-    restore_monitors();
     _full_screen = false;
     restore_screens_size();
     show();
commit 0b07ca2775888a10d64e51fb95425ff932fc4422
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Oct 17 10:43:28 2010 +0200

    spicec-x11: Change WmSizeHints in fullscreen mode
    
    Some window managers will ignore the fullscreen hint, unless WmSizeHints
    allow them to resize the window so that they can give it the size of
    the roo-window. This fixes fullscreen mode in compiz.

diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index e7b6815..8f6535b 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -1063,18 +1063,27 @@ void RedWindow_p::set_glx(int width, int height)
 }
 #endif // USE_OGL
 
-void RedWindow_p::set_minmax(PixelsSource_p& pix_source, int width, int height)
+void RedWindow_p::set_minmax(PixelsSource_p& pix_source)
 {
     //todo: auto res
     XSizeHints* size_hints = XAllocSizeHints();
     ASSERT(size_hints);
     size_hints->flags = PMinSize | PMaxSize;
-    size_hints->min_width = size_hints->max_width = width;
-    size_hints->min_height = size_hints->max_height = height;
+    if (_red_window->_type == RedWindow::TYPE_FULLSCREEN) {
+        /* Some window managers won't allow full screen mode with a fixed
+           width / height */
+        size_hints->min_width = 1;
+        size_hints->max_width = 65535;
+        size_hints->min_height = 1;
+        size_hints->max_height = 65535;
+    } else {
+        size_hints->min_width = size_hints->max_width = _width;
+        size_hints->min_height = size_hints->max_height = _height;
+    }
     XSetWMNormalHints(x_display, _win, size_hints);
     XFree(size_hints);
-    pix_source.x_drawable.height = height;
-    pix_source.x_drawable.width = width;
+    pix_source.x_drawable.height = _height;
+    pix_source.x_drawable.width = _width;
 }
 
 Cursor RedWindow_p::create_invisible_cursor(Window window)
@@ -1100,6 +1109,8 @@ RedWindow_p::RedWindow_p()
     , _ignore_foucs (false)
     , _pointer_in_window (false)
     , _ignore_pointer (false)
+    ,_width (200)
+    ,_height (200)
 {
 }
 
@@ -1145,8 +1156,8 @@ void RedWindow_p::destroy(RedWindow& red_window, PixelsSource_p& pix_source)
     }
 }
 
-void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source, int x, int y,
-                         unsigned int width, unsigned int height, int in_screen)
+void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source,
+                         int x, int y, int in_screen)
 {
     Window window = None;
     Cursor cursor = None;
@@ -1168,7 +1179,7 @@ void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source, int
     win_attributes.colormap = _colormap;
     mask |= CWColormap;
     window = XCreateWindow(x_display, root_window, x, y,
-                           width, height, 0, XPlatform::get_vinfo()[in_screen]->depth,
+                           _width, _height, 0, XPlatform::get_vinfo()[in_screen]->depth,
                            InputOutput, XPlatform::get_vinfo()[in_screen]->visual, mask,
                            &win_attributes);
     XUnlockDisplay(x_display);
@@ -1223,11 +1234,12 @@ void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source, int
     _show_pos.y = y;
     _visibale = false;
     _expect_parent = false;
+    _red_window = &red_window;
     pix_source.type = PIXELS_SOURCE_TYPE_X_DRAWABLE;
     pix_source.x_drawable.drawable = window;
     pix_source.x_drawable.screen = _screen;
     pix_source.x_drawable.gc = gc;
-    set_minmax(pix_source, width, height);
+    set_minmax(pix_source);
     sync();
 }
 
@@ -1236,17 +1248,12 @@ void RedWindow_p::migrate(RedWindow& red_window, PixelsSource_p& pix_source, int
     if (to_screen == _screen) {
         return;
     }
-    XWindowAttributes attrib;
-    if (!XGetWindowAttributes(x_display, _win, &attrib)) {
-        THROW("get attributes failed");
-    }
     XTextProperty text_pro;
     XLockDisplay(x_display);
     bool valid_title = XGetWMName(x_display, _win, &text_pro) && text_pro.value;
     XUnlockDisplay(x_display);
     destroy(red_window, pix_source);
-    create(red_window, pix_source, _show_pos.x, _show_pos.y, attrib.width, attrib.height,
-           to_screen);
+    create(red_window, pix_source, _show_pos.x, _show_pos.y, to_screen);
     if (valid_title) {
         XSetWMName(x_display, _win, &text_pro);
         XFree(text_pro.value); //???
@@ -1304,7 +1311,7 @@ RedWindow::RedWindow(RedWindow::Listener& listener, int screen)
     , _menu (NULL)
 {
     ASSERT(x_display);
-    create(*this, *(PixelsSource_p*)get_opaque(), 0, 0, 200, 200,
+    create(*this, *(PixelsSource_p*)get_opaque(), 0, 0,
            (screen == DEFAULT_SCREEN) ? DefaultScreen(x_display) : screen);
 }
 
@@ -1505,6 +1512,9 @@ void RedWindow::show(int screen_id)
         _listener.post_migrate();
     }
 
+    /* We must update min/max for fullscreen / normal switching */
+    set_minmax(*(PixelsSource_p*)get_opaque());
+
     if (_type == TYPE_FULLSCREEN) {
         Atom state[2];
         state[0] = wm_state_above;
@@ -1621,7 +1631,9 @@ static void send_expose(Window window, int width, int height)
 
 void RedWindow::move_and_resize(int x, int y, int width, int height)
 {
-    set_minmax(*(PixelsSource_p*)get_opaque(), width, height);
+    _width = width;
+    _height = height;
+    set_minmax(*(PixelsSource_p*)get_opaque());
     XMoveResizeWindow(x_display, _win, x, y, width, height);
     _show_pos.x = x;
     _show_pos.y = y;
@@ -1639,7 +1651,9 @@ void RedWindow::move(int x, int y)
 
 void RedWindow::resize(int width, int height)
 {
-    set_minmax(*(PixelsSource_p*)get_opaque(), width, height);
+    _width = width;
+    _height = height;
+    set_minmax(*(PixelsSource_p*)get_opaque());
     XResizeWindow(x_display, _win, width, height);
     if (_visibale) {
         send_expose(_win, width, height);
diff --git a/client/x11/red_window_p.h b/client/x11/red_window_p.h
index 29121d9..8f14d4e 100644
--- a/client/x11/red_window_p.h
+++ b/client/x11/red_window_p.h
@@ -39,10 +39,10 @@ public:
     RedWindow_p();
 
     void migrate(RedWindow& red_window, PixelsSource_p& pix_source, int dest_screen);
-    void create(RedWindow& red_window, PixelsSource_p& pix_source, int x, int y,
-                unsigned int width, unsigned int height, int in_screen);
+    void create(RedWindow& red_window, PixelsSource_p& pix_source,
+                int x, int y, int in_screen);
     void destroy(RedWindow& red_window, PixelsSource_p& pix_source);
-    void set_minmax(PixelsSource_p& pix_source, int width, int height);
+    void set_minmax(PixelsSource_p& pix_source);
     void wait_for_reparent();
     void wait_for_map();
     void wait_for_unmap();
@@ -79,6 +79,9 @@ protected:
     bool _shadow_pointer_state;
     XEvent _shadow_pointer_event;
     Colormap _colormap;
+    RedWindow *_red_window;
+    int _width;
+    int _height;
 };
 
 #endif
commit 203a39761f7da9547e5856efbb2b5f51ac63f369
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Oct 17 10:41:13 2010 +0200

    spicec-x11: Add missing XLockDisplay around XRRSet* calls
    
    XRRSet* calls wait for a XReply, so add a missing XLockDisplay,
    this fixes a hang (due to a race so not always) when switching between
    windowed and fullscreen mode.

diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index 0642922..13bc0a6 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -1026,8 +1026,10 @@ bool DynamicScreen::set_screen_size(int size_index)
     XRRConfigCurrentConfiguration(config, &rotation);
 
     Monitor::self_monitors_change++;
+    XLockDisplay(get_display());
     /*what status*/
     XRRSetScreenConfig(get_display(), config, root_window, size_index, rotation, CurrentTime);
+    XUnlockDisplay(get_display());
     process_monitor_configure_events(platform_win);
     Monitor::self_monitors_change--;
     XRRFreeScreenConfigInfo(config);
@@ -1300,7 +1302,9 @@ void MultyMonScreen::set_size(int width, int height)
     int width_mm = (int)((double)_saved_width_mm / _saved_width * width);
     set_height(height);
     int height_mm = (int)((double)_saved_height_mm / _saved_height * height);
+    XLockDisplay(get_display());
     XRRSetScreenSize(get_display(), root_window, width, height, width_mm, height_mm);
+    XUnlockDisplay(get_display());
     X_DEBUG_SYNC(get_display());
 }
 
@@ -1329,9 +1333,11 @@ void MultyMonScreen::restore()
     disable();
     Window root_window = RootWindow(get_display(), get_screen());
 
+    XLockDisplay(get_display());
     XRRSetScreenSize(get_display(), root_window, _saved_width,
                      _saved_height,
                      _saved_width_mm, _saved_height_mm);
+    XUnlockDisplay(get_display());
     XMonitorsList::iterator iter = _monitors.begin();
     for (; iter != _monitors.end(); iter++) {
         (*iter)->revert();
@@ -2150,8 +2156,10 @@ void XMonitor::disable()
     if (!res.valid()) {
         THROW("get screen resources failed");
     }
+    XLockDisplay(display);
     XRRSetCrtcConfig(display, res.get(), _crtc, CurrentTime,
                      0, 0, None, RR_Rotate_0, NULL, 0);
+    XUnlockDisplay(display);
 
     XMonitorsList::iterator iter = _clones.begin();
     for (; iter != _clones.end(); iter++) {
@@ -2174,10 +2182,12 @@ void XMonitor::enable()
     if (!res.valid()) {
         THROW("get screen resources failed");
     }
+    XLockDisplay(display);
     XRRSetCrtcConfig(display, res.get(), _crtc, CurrentTime,
                      _position.x, _position.y,
                      _mode, _rotation,
                      _outputs, _noutput);
+    XUnlockDisplay(display);
 
     XMonitorsList::iterator iter = _clones.begin();
     for (; iter != _clones.end(); iter++) {
commit 607d58f4eb7abeb29329f7ddc1a7aa3700bc95a3
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Oct 16 20:53:21 2010 +0200

    client: Do not try to send display_config until we've received the agent caps
    
    Currenty, we check the agent caps in RedClient::handle_agent_connected
    for VD_AGENT_CAP_DISPLAY_CONFIG and if present send display_config, but at
    this time we have not received the caps yet, so remove this.
    
    Also the send_agent_display_config call in on_agent_announce_capabilities
    lacks a check for _agent_disp_config_sent, and we send the display config
    before announcing that we may do so by sending our own caps, which seems
    inpolite.

diff --git a/client/red_client.cpp b/client/red_client.cpp
index b9e1421..0fc4815 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -1011,11 +1011,6 @@ void RedClient::handle_agent_connected(RedPeer::InMessage* message)
     if (_auto_display_res && !_agent_mon_config_sent) {
         send_agent_monitors_config();
     }
-
-    if (VD_AGENT_HAS_CAPABILITY(_agent_caps, _agent_caps_size,
-            VD_AGENT_CAP_DISPLAY_CONFIG) && !_agent_disp_config_sent) {
-        send_agent_display_config();
-    }
 }
 
 void RedClient::handle_agent_disconnected(RedPeer::InMessage* message)
@@ -1037,15 +1032,15 @@ void RedClient::on_agent_announce_capabilities(
     }
     memcpy(_agent_caps, caps->caps, sizeof(_agent_caps[0]) * caps_size);
 
+    if (caps->request) {
+        send_agent_announce_capabilities(false);
+    }
     if (VD_AGENT_HAS_CAPABILITY(caps->caps, caps_size,
-            VD_AGENT_CAP_DISPLAY_CONFIG)) {
+            VD_AGENT_CAP_DISPLAY_CONFIG) && !_agent_disp_config_sent) {
         // not sending the color depth through send_agent_monitors_config, since
         // it applies only for attached screens.
         send_agent_display_config();
     }
-    if (caps->request) {
-        send_agent_announce_capabilities(false);
-    }
 }
 
 void RedClient::on_agent_reply(VDAgentReply* reply)


More information about the Spice-commits mailing list