[Spice-devel] [PATCH] client: add xinerama support

Alon Levy alevy at redhat.com
Sun Nov 13 03:33:49 PST 2011


On Sun, Nov 13, 2011 at 01:19:37PM +0200, Alon Levy wrote:
> From: Arnon Gilboa <agilboa at agilboa.usersys.redhat.com>
> 

This patch's subject should have been "PATCH v2", please review.

Like it says, it is a cherry-pick from RHEL-5 commits by Arnon and
Yonit.

> RHEL-6 Bugzilla: 695323
> 
> cherry-picked from qspice commit
>  003667ac99beeec9b330a07bc3569c59a96d4588
>  which fixes RHEL-5 541566
> 
> with merge of the one line qspice fix to SPICE_REQUIRES:
>  9f3fe4755f11044a45c4b21148466a997fcbf735
>  spice: fixed reference to xinerama pkg config file
>  (Xinerama.pc=>xinerama.pc)
>  Author: Yonit Halperin <yhalperi at redhat.com>
> ---
>  client/Makefile.am      |    2 +
>  client/x11/platform.cpp |  147 +++++++++++++++++++++++++++++++++++++++++++++++
>  configure.ac            |   15 +++++
>  3 files changed, 164 insertions(+), 0 deletions(-)
> 
> diff --git a/client/Makefile.am b/client/Makefile.am
> index 2508267..f7c9c56 100644
> --- a/client/Makefile.am
> +++ b/client/Makefile.am
> @@ -226,6 +226,7 @@ INCLUDES = \
>  	$(XRANDR_CFLAGS)				\
>  	$(XFIXES_CFLAGS)				\
>  	$(WARN_CFLAGS)					\
> +	$(XINERAMA_CFLAGS)				\
>  	$(NULL)
>  
>  spicec_LDFLAGS = $(SPICEC_STATIC_LINKAGE_BSTATIC)
> @@ -246,6 +247,7 @@ spicec_LDADD =						\
>  	$(XFIXES_LIBS)					\
>  	$(XRANDR_LIBS)					\
>  	$(Z_LIBS)					\
> +	$(XINERAMA_LIBS)				\
>  	$(NULL)
>  
>  EXTRA_DIST =				\
> diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
> index aef6870..9094a64 100644
> --- a/client/x11/platform.cpp
> +++ b/client/x11/platform.cpp
> @@ -74,6 +74,11 @@
>  #define USE_XRANDR_1_2
>  #endif
>  
> +#ifdef HAVE_XINERAMA
> +#include <X11/extensions/Xinerama.h>
> +#define USE_XINERAMA_1_0
> +#endif
> +
>  static Display* x_display = NULL;
>  static bool x_shm_avail = false;
>  static XVisualInfo **vinfo = NULL;
> @@ -106,6 +111,10 @@ static bool using_xfixes_1_0 = false;
>  static int xfixes_event_base;
>  static int xfixes_error_base;
>  
> +#ifdef USE_XINERAMA_1_0
> +static bool using_xinerama_1_0 = false;
> +#endif
> +
>  static unsigned int caps_lock_mask = 0;
>  static unsigned int num_lock_mask = 0;
>  
> @@ -1069,6 +1078,91 @@ bool DynamicScreen::set_screen_size(int size_index)
>      return true;
>  }
>  
> +#ifdef USE_XINERAMA_1_0
> +
> +class XineramaMonitor;
> +typedef std::list<XineramaMonitor*> XineramaMonitorsList;
> +
> +class XineramaScreen : public XScreen {
> +public:
> +    XineramaScreen(Display* display, int screen, int& next_mon_id, XineramaScreenInfo* xin_screens,
> +                   int num_xin_screens);
> +    virtual ~XineramaScreen();
> +
> +    void publish_monitors(MonitorsList& monitors);
> +
> +private:
> +    XineramaMonitorsList _monitors;
> +};
> +
> +class XineramaMonitor : public Monitor {
> +public:
> +    XineramaMonitor(int id, XineramaScreenInfo& xin_screen);
> +
> +    virtual void do_set_mode(int width, int height);
> +    virtual void do_restore() {}
> +    virtual int get_depth() { return 32;}
> +    virtual SpicePoint get_position() { return _position;}
> +    virtual SpicePoint get_size() const { return _size;}
> +    virtual bool is_out_of_sync() { return _out_of_sync;}
> +    virtual int get_screen_id() { return 0;}
> +
> +private:
> +    SpicePoint _position;
> +    SpicePoint _size;
> +    bool _out_of_sync;
> +};
> +
> +XineramaScreen::XineramaScreen(Display* display, int screen, int& next_mon_id,
> +                               XineramaScreenInfo* xin_screens, int num_xin_screens)
> +    : XScreen(display, screen)
> +{
> +    X_DEBUG_SYNC(display);
> +    for (int i = 0; i < num_xin_screens; i++) {
> +        _monitors.push_back(new XineramaMonitor(next_mon_id++, xin_screens[i]));
> +    }
> +    Window root_window = RootWindow(display, screen);
> +    XSelectInput(display, root_window, StructureNotifyMask);
> +    XRRSelectInput(display, root_window, RRScreenChangeNotifyMask);     // TODO: this fails if we don't have RR extension (but do have XINERAMA)
> +    XPlatform::set_win_proc(root_window, root_win_proc);     // Xlib:  extension "RANDR" missing on display ":3.0".
> +    X_DEBUG_SYNC(display);
> +}
> +
> +XineramaScreen::~XineramaScreen()
> +{
> +    while (!_monitors.empty()) {
> +        XineramaMonitor* monitor = _monitors.front();
> +        _monitors.pop_front();
> +        delete monitor;
> +    }
> +}
> +
> +void XineramaScreen::publish_monitors(MonitorsList& monitors)
> +{
> +    XineramaMonitorsList::iterator iter = _monitors.begin();
> +    for (; iter != _monitors.end(); iter++) {
> +        monitors.push_back(*iter);
> +    }
> +}
> +
> +XineramaMonitor::XineramaMonitor(int id, XineramaScreenInfo& screen_info)
> +    : Monitor(id)
> +    , _out_of_sync (false)
> +{
> +    _position.x = screen_info.x_org;
> +    _position.y = screen_info.y_org;
> +    _size.x = screen_info.width;
> +    _size.y = screen_info.height;
> +}
> +
> +
> +void XineramaMonitor::do_set_mode(int width, int height)
> +{
> +    _out_of_sync = width > _size.x || height > _size.y;
> +}
> +
> +#endif
> +
>  #ifdef USE_XRANDR_1_2
>  
>  class MultyMonScreen: public XScreen {
> @@ -2314,6 +2408,35 @@ void XMonitor::set_mode(const XRRModeInfo& mode)
>  
>  #endif
>  
> +#ifdef USE_XINERAMA_1_0
> +
> +static XineramaScreenInfo* init_xinerama_screens(int* num_xin_screens)
> +{
> +    XineramaScreenInfo* xin_screens = NULL;
> +
> +    if (using_xinerama_1_0 && ScreenCount(x_display) == 1) {
> +        int ncrtc = 0;
> +#ifdef USE_XRANDR_1_2
> +        if (using_xrandr_1_2) {
> +            AutoScreenRes res(XRRGetScreenResources(x_display, RootWindow(x_display, 0)));
> +            if (res.valid()) {
> +                ncrtc = res->ncrtc;
> +            }
> +        }
> +#endif
> +        if (ncrtc < 2) {
> +            xin_screens = XineramaQueryScreens(x_display, num_xin_screens);
> +        }
> +    }
> +    if (xin_screens && *num_xin_screens < 2) {
> +        XFree(xin_screens);
> +        return NULL;
> +    }
> +    return xin_screens;
> +}
> +
> +#endif
> +
>  static MonitorsList monitors;
>  static Monitor* primary_monitor = NULL;
>  
> @@ -2324,6 +2447,15 @@ const MonitorsList& Platform::init_monitors()
>  {
>      int next_mon_id = 0;
>      ASSERT(screens.empty());
> +
> +#ifdef USE_XINERAMA_1_0
> +    int num_xin_screens;
> +    XineramaScreenInfo* xin_screens = init_xinerama_screens(&num_xin_screens);
> +    if (xin_screens) {
> +        screens.push_back(new XineramaScreen(x_display, 0, next_mon_id, xin_screens, num_xin_screens));
> +        XFree(xin_screens);
> +    } else
> +#endif
>  #ifdef USE_XRANDR_1_2
>      if (using_xrandr_1_2) {
>          for (int i = 0; i < ScreenCount(x_display); i++) {
> @@ -2944,6 +3076,20 @@ static void init_xrender()
>          XRenderQueryVersion(x_display, &major, &minor) && (major > 0 || minor >= 5);
>  }
>  
> +static void init_xinerama()
> +{
> +#ifdef USE_XINERAMA_1_0
> +    int event_base;
> +    int error_base;
> +    int major;
> +    int minor;
> +
> +    using_xinerama_1_0 = XineramaQueryExtension(x_display, &event_base, &error_base) &&
> +        XineramaQueryVersion(x_display, &major, &minor) && major >= 1 && minor >= 0 &&
> +        XineramaIsActive(x_display);
> +#endif
> +}
> +
>  static void init_xfixes()
>  {
>      int major;
> @@ -3148,6 +3294,7 @@ void Platform::init()
>      init_xrender();
>      init_xfixes();
>      init_XIM();
> +    init_xinerama();
>  
>      struct sigaction act;
>      memset(&act, 0, sizeof(act));
> diff --git a/configure.ac b/configure.ac
> index 646cbe7..861e939 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -283,6 +283,19 @@ if test "$red_target" = "x11"; then
>  	AC_SUBST(MISC_X_LIBS)
>  fi
>  
> +PKG_CHECK_MODULES(XINERAMA,
> +        xinerama >= 1.0,
> +        have_xinerama=yes,
> +        have_xinerama=no)
> +
> +AM_CONDITIONAL([HAVE_XINERAMA], [test "x$have_xinerama" = "xyes"])
> +if test "x$have_xinerama" = "xyes" ; then
> +  AC_DEFINE([HAVE_XINERAMA], [], [Define if we have Xinerama])
> +  AC_SUBST(XINERAMA_CFLAGS)
> +  AC_SUBST(XINERAMA_LIBS)
> +  SPICE_REQUIRES+=" xinerama"
> +fi
> +
>  # Add parameter for (partial) static linkage of spice client.
>  # this is used to achive single binary package for all (?) distros.
>  AC_ARG_ENABLE(static-linkage,
> @@ -523,6 +536,8 @@ echo "
>  
>          Have XRANDR 1.2:          ${have_xrandr12}
>  
> +        Have Xinerama:            ${have_xinerama}
> +
>          Support tunneling:        ${enable_tunnel}
>  
>          Red target:               ${red_target}
> -- 
> 1.7.7.3
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list