From 6cb277798e17532ef4b7b4cbb6bfec293a6dc7e8 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 11 May 2012 12:13:23 +0200 Subject: [PATCH] Resolves: rhbz#809019 Impress thinks a machine with 2 monitors in clone mode is multihead --- ...09019-count-mirrored-monitors-as-one.patch | 269 ++++++++++++++++++ libreoffice.spec | 4 + 2 files changed, 273 insertions(+) create mode 100644 0001-rhbz-809019-count-mirrored-monitors-as-one.patch diff --git a/0001-rhbz-809019-count-mirrored-monitors-as-one.patch b/0001-rhbz-809019-count-mirrored-monitors-as-one.patch new file mode 100644 index 0000000..b0a8f38 --- /dev/null +++ b/0001-rhbz-809019-count-mirrored-monitors-as-one.patch @@ -0,0 +1,269 @@ +From 83dd316f42bcc959a533e6be2ba24bbc37417a0a Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Wed, 25 Apr 2012 15:08:53 +0200 +Subject: [PATCH] rhbz#809019 count mirrored monitors as one + +Change-Id: I I I184541e99ab4e04b8534dd0341bc2f3630094e9c +--- + vcl/inc/unx/gtk/gtkdata.hxx | 2 + + vcl/inc/unx/gtk/gtksys.hxx | 11 ++++- + vcl/unx/gtk/app/gtkdata.cxx | 2 + + vcl/unx/gtk/app/gtksys.cxx | 85 ++++++++++++++++++++++++++++++-------- + vcl/unx/gtk/window/gtkframe.cxx | 4 +- + 5 files changed, 81 insertions(+), 23 deletions(-) + +diff --git a/vcl/inc/unx/gtk/gtkdata.hxx b/vcl/inc/unx/gtk/gtkdata.hxx +index 63b8ae3..033bf1a 100644 +--- a/vcl/inc/unx/gtk/gtkdata.hxx ++++ b/vcl/inc/unx/gtk/gtkdata.hxx +@@ -151,6 +151,8 @@ public: + GdkDisplay* GetGdkDisplay() const { return m_pGdkDisplay; } + bool IsX11Display() const { return m_bX11Display; } + ++ GtkSalSystem* getSystem() const { return m_pSys; } ++ + virtual void deregisterFrame( SalFrame* pFrame ); + GdkCursor *getCursor( PointerStyle ePointerStyle ); + virtual int CaptureMouse( SalFrame* pFrame ); +diff --git a/vcl/inc/unx/gtk/gtksys.hxx b/vcl/inc/unx/gtk/gtksys.hxx +index df9e79e..582d4b9 100644 +--- a/vcl/inc/unx/gtk/gtksys.hxx ++++ b/vcl/inc/unx/gtk/gtksys.hxx +@@ -36,7 +36,11 @@ + + class GtkSalSystem : public SalGenericSystem + { ++ typedef std::deque > ScreenMonitors_t; ++ + GdkDisplay *mpDisplay; ++ // Number of monitors for every active screen. ++ ScreenMonitors_t maScreenMonitors; + public: + GtkSalSystem(); + virtual ~GtkSalSystem(); +@@ -56,10 +60,11 @@ public: + { return getXScreenFromDisplayScreen( GetDisplayDefaultScreen() ); } + int GetDisplayXScreenCount(); + SalX11Screen getXScreenFromDisplayScreen(unsigned int nDisplayScreen); ++ void countScreenMonitors(); + // We have a 'screen' number that is combined from screen-idx + monitor-idx +- static int getScreenIdxFromPtr (GdkDisplay *pDisplay, GdkScreen *pScreen); +- static int getScreenMonitorIdx (GdkDisplay *pDisplay, GdkScreen *pScreen, int nX, int nY); +- static GdkScreen *getScreenMonitorFromIdx (GdkDisplay *pDisplay, int nIdx, gint &nMonitor); ++ int getScreenIdxFromPtr (GdkScreen *pScreen); ++ int getScreenMonitorIdx (GdkScreen *pScreen, int nX, int nY); ++ GdkScreen *getScreenMonitorFromIdx (int nIdx, gint &nMonitor); + }; + + #endif // _VCL_GTKSYS_HXX_ +diff --git a/vcl/unx/gtk/app/gtkdata.cxx b/vcl/unx/gtk/app/gtkdata.cxx +index 5189174..4d58110 100644 +--- a/vcl/unx/gtk/app/gtkdata.cxx ++++ b/vcl/unx/gtk/app/gtkdata.cxx +@@ -197,12 +197,14 @@ GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event, + + void GtkSalDisplay::screenSizeChanged( GdkScreen* pScreen ) + { ++ m_pSys->countScreenMonitors(); + if (pScreen) + emitDisplayChanged(); + } + + void GtkSalDisplay::monitorsChanged( GdkScreen* pScreen ) + { ++ m_pSys->countScreenMonitors(); + if (pScreen) + emitDisplayChanged(); + } +diff --git a/vcl/unx/gtk/app/gtksys.cxx b/vcl/unx/gtk/app/gtksys.cxx +index 538107f..25578b3 100644 +--- a/vcl/unx/gtk/app/gtksys.cxx ++++ b/vcl/unx/gtk/app/gtksys.cxx +@@ -49,6 +49,7 @@ SalSystem *GtkInstance::CreateSalSystem() + GtkSalSystem::GtkSalSystem() : SalGenericSystem() + { + mpDisplay = gdk_display_get_default(); ++ countScreenMonitors(); + } + + GtkSalSystem::~GtkSalSystem() +@@ -61,6 +62,52 @@ GtkSalSystem::GetDisplayXScreenCount() + return gdk_display_get_n_screens (mpDisplay); + } + ++namespace ++{ ++ ++struct GdkRectangleEqual ++{ ++ bool operator()(GdkRectangle const& rLeft, GdkRectangle const& rRight) ++ { ++ return ++ rLeft.x == rRight.x ++ && rLeft.y == rRight.y ++ && rLeft.width == rRight.width ++ && rLeft.height == rRight.height ++ ; ++ } ++}; ++ ++} ++ ++void ++GtkSalSystem::countScreenMonitors() ++{ ++ maScreenMonitors.clear(); ++ for (gint i = 0; i < gdk_display_get_n_screens(mpDisplay); i++) ++ { ++ GdkScreen* const pScreen(gdk_display_get_screen(mpDisplay, i)); ++ gint nMonitors(pScreen ? gdk_screen_get_n_monitors(pScreen) : 0); ++ if (nMonitors > 1) ++ { ++ std::vector aGeometries; ++ aGeometries.reserve(nMonitors); ++ for (gint j(0); j != nMonitors; ++j) ++ { ++ GdkRectangle aGeometry; ++ gdk_screen_get_monitor_geometry(pScreen, j, &aGeometry); ++ aGeometries.push_back(aGeometry); ++ } ++ GdkRectangleEqual aCmp; ++ std::sort(aGeometries.begin(), aGeometries.end(), aCmp); ++ const std::vector::iterator aUniqueEnd( ++ std::unique(aGeometries.begin(), aGeometries.end(), aCmp)); ++ nMonitors = std::distance(aGeometries.begin(), aUniqueEnd); ++ } ++ maScreenMonitors.push_back(std::make_pair(pScreen, nMonitors)); ++ } ++} ++ + // Including gdkx.h kills us with the Window / XWindow conflict + extern "C" { + GType gdk_x11_display_get_type (void); +@@ -73,7 +120,7 @@ GtkSalSystem::getXScreenFromDisplayScreen(unsigned int nScreen) + gint nMonitor; + GdkScreen *pScreen = NULL; + +- pScreen = getScreenMonitorFromIdx (mpDisplay, nScreen, nMonitor); ++ pScreen = getScreenMonitorFromIdx (nScreen, nMonitor); + if (!pScreen) + return SalX11Screen (0); + #if GTK_CHECK_VERSION(3,0,0) +@@ -84,16 +131,16 @@ GtkSalSystem::getXScreenFromDisplayScreen(unsigned int nScreen) + } + + GdkScreen * +-GtkSalSystem::getScreenMonitorFromIdx (GdkDisplay *pDisplay, int nIdx, gint &nMonitor) ++GtkSalSystem::getScreenMonitorFromIdx (int nIdx, gint &nMonitor) + { + GdkScreen *pScreen = NULL; +- for (gint i = 0; i < gdk_display_get_n_screens (pDisplay); i++) ++ for (ScreenMonitors_t::const_iterator aIt(maScreenMonitors.begin()), aEnd(maScreenMonitors.end()); aIt != aEnd; ++aIt) + { +- pScreen = gdk_display_get_screen (pDisplay, i); ++ pScreen = aIt->first; + if (!pScreen) + break; +- if (nIdx >= gdk_screen_get_n_monitors (pScreen)) +- nIdx -= gdk_screen_get_n_monitors (pScreen); ++ if (nIdx >= aIt->second) ++ nIdx -= aIt->second; + else + break; + } +@@ -102,32 +149,34 @@ GtkSalSystem::getScreenMonitorFromIdx (GdkDisplay *pDisplay, int nIdx, gint &nMo + } + + int +-GtkSalSystem::getScreenIdxFromPtr (GdkDisplay *pDisplay, GdkScreen *pScreen) ++GtkSalSystem::getScreenIdxFromPtr (GdkScreen *pScreen) + { + int nIdx = 0; +- for (gint i = 0; i < gdk_display_get_n_screens (pDisplay); i++) ++ for (ScreenMonitors_t::const_iterator aIt(maScreenMonitors.begin()), aEnd(maScreenMonitors.end()); aIt != aEnd; ++aIt) + { +- GdkScreen *pCmp = gdk_display_get_screen (pDisplay, i); +- if (pCmp == pScreen) ++ if (aIt->first == pScreen) + return nIdx; +- nIdx += gdk_screen_get_n_monitors (pCmp); ++ nIdx += aIt->second; + } + g_warning ("failed to find screen %p", pScreen); + return 0; + } + +-int GtkSalSystem::getScreenMonitorIdx (GdkDisplay *pDisplay, +- GdkScreen *pScreen, ++int GtkSalSystem::getScreenMonitorIdx (GdkScreen *pScreen, + int nX, int nY) + { +- return getScreenIdxFromPtr (pDisplay, pScreen) + ++ // TODO: this will fail horribly for exotic combinations like two ++ // monitors in mirror mode and one extra. Hopefully such ++ // abominations are not used (or, even better, not possible) in ++ // practice .-) ++ return getScreenIdxFromPtr (pScreen) + + gdk_screen_get_monitor_at_point (pScreen, nX, nY); + } + + unsigned int GtkSalSystem::GetDisplayScreenCount() + { + gint nMonitor; +- (void)getScreenMonitorFromIdx (mpDisplay, G_MAXINT, nMonitor); ++ (void)getScreenMonitorFromIdx (G_MAXINT, nMonitor); + return G_MAXINT - nMonitor; + } + +@@ -183,7 +232,7 @@ static int _get_primary_monitor (GdkScreen *pScreen) + unsigned int GtkSalSystem::GetDisplayDefaultScreen() + { + GdkScreen *pDefault = gdk_display_get_default_screen (mpDisplay); +- int idx = getScreenIdxFromPtr (mpDisplay, pDefault); ++ int idx = getScreenIdxFromPtr (pDefault); + return idx + _get_primary_monitor (pDefault); + } + +@@ -192,7 +241,7 @@ Rectangle GtkSalSystem::GetDisplayScreenPosSizePixel (unsigned int nScreen) + gint nMonitor; + GdkScreen *pScreen; + GdkRectangle aRect; +- pScreen = getScreenMonitorFromIdx (mpDisplay, nScreen, nMonitor); ++ pScreen = getScreenMonitorFromIdx (nScreen, nMonitor); + if (!pScreen) + return Rectangle(); + gdk_screen_get_monitor_geometry (pScreen, nMonitor, &aRect); +@@ -212,7 +261,7 @@ rtl::OUString GtkSalSystem::GetDisplayScreenName(unsigned int nScreen) + gchar *pStr; + gint nMonitor; + GdkScreen *pScreen; +- pScreen = getScreenMonitorFromIdx (mpDisplay, nScreen, nMonitor); ++ pScreen = getScreenMonitorFromIdx (nScreen, nMonitor); + if (!pScreen) + return rtl::OUString(); + +diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx +index 28776f1..eb77e75 100644 +--- a/vcl/unx/gtk/window/gtkframe.cxx ++++ b/vcl/unx/gtk/window/gtkframe.cxx +@@ -593,7 +593,7 @@ void GtkSalFrame::updateScreenNumber() + int nScreen = 0; + GdkScreen *pScreen = gtk_widget_get_screen( m_pWindow ); + if( pScreen ) +- nScreen = GtkSalSystem::getScreenMonitorIdx( getGdkDisplay(), pScreen, maGeometry.nX, maGeometry.nY ); ++ nScreen = getDisplay()->getSystem()->getScreenMonitorIdx( pScreen, maGeometry.nX, maGeometry.nY ); + maGeometry.nDisplayScreenNumber = nScreen; + } + +@@ -1862,7 +1862,7 @@ void GtkSalFrame::SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSiz + + gint nMonitor; + GdkScreen *pScreen = NULL; +- pScreen = GtkSalSystem::getScreenMonitorFromIdx( getGdkDisplay(), nNewScreen, nMonitor ); ++ pScreen = getDisplay()->getSystem()->getScreenMonitorFromIdx( nNewScreen, nMonitor ); + + // Heavy lifting, need to move screen ... + if( pScreen != gtk_widget_get_screen( m_pWindow )) +-- +1.7.7.6 + diff --git a/libreoffice.spec b/libreoffice.spec index e0d4f27..c2e2b2a 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -148,6 +148,7 @@ Patch34: 0001-Resolves-rhbz-805743-a11y-call-doShow-after-we-have-.patch Patch35: 0001-do-not-prepend-n-twice-it-confuses-KFileDialog-rhbz-.patch Patch36: 0001-incrementing-index-twice-in-one-run-seems-wrong.patch Patch37: 0001-fdo-49365-correctly-map-monitor-index-back-to-screen.patch +Patch38: 0001-rhbz-809019-count-mirrored-monitors-as-one.patch %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} %define instdir %{_libdir} @@ -1012,6 +1013,7 @@ mv -f redhat.soc extras/source/palettes/standard.soc %patch35 -p1 -b .do-not-prepend-n-twice-it-confuses-KFileDialog-rhbz-.patch %patch36 -p1 -b .rhbz-809019-count-mirrored-monitors-as-one.patch %patch37 -p1 -b .incrementing-index-twice-in-one-run-seems-wrong.patch +%patch38 -p1 -b .rhbz-809019-count-mirrored-monitors-as-one.patch # TODO: check this # these are horribly incomplete--empty translations and copied english @@ -2303,6 +2305,8 @@ update-desktop-database %{_datadir}/applications &> /dev/null || : - Resolves: rhbz#820439 KDE export dialog broken for most formats - Resolves: fdo#49365 Libreoffice fails to start on second screen with gtk vcl plugin +- Resolves: rhbz#809019 Impress thinks a machine with 2 monitors in + clone mode is multihead * Wed May 09 2012 Caolán McNamara - 3.5.3.2-3 - Resolves: rhbz#805743 a11y crash in impress/draw