From 3d24c779ae0551ecb45e6a1a7d62460e830619c0 Mon Sep 17 00:00:00 2001
From: Tomas Janousek <tomi@nomi.cz>
Date: Mon, 26 Feb 2007 00:25:55 +0100
Subject: [PATCH] Reload the Xinerama layout on RandR signal. This is probably just a

workaround for some issues, not a final solution -- but it points out the
problems.
---
 src/Screen.cc |   34 ++++++++++++++++++++++++++--------
 src/Screen.hh |    2 +-
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/src/Screen.cc b/src/Screen.cc
index 812f786..d992306 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -373,6 +373,12 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
 
     Display *disp = m_root_window.display();
 
+    // TODO fluxgen: check if this is the right place (it was not -lis)
+    //
+    // Create the first one, initXinerama will expand this if needed.
+    m_head_areas.resize(1);
+    m_head_areas[0] = new HeadArea();
+
     initXinerama();
 
     // setup error handler to catch "screen already managed by other wm"
@@ -406,9 +412,6 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
         XFree(ret_prop);
     }
 
-    // TODO fluxgen: check if this is the right place
-    m_head_areas = new HeadArea[numHeads() ? numHeads() : 1];
-
     _FB_USES_NLS;
 
     fprintf(stderr, _FB_CONSOLETEXT(Screen, ManagingScreen,
@@ -603,7 +606,8 @@ BScreen::~BScreen() {
     m_slit.reset(0);
 
     // TODO fluxgen: check if this is the right place
-    delete [] m_head_areas;
+    for (int i = 0; i < m_head_areas.size(); i++)
+	delete m_head_areas[i];
 
     delete m_focus_control;
     delete m_placement_strategy;
@@ -720,7 +724,7 @@ unsigned int BScreen::currentWorkspaceID() const {
 }
 
 const Strut* BScreen::availableWorkspaceArea(int head) const {
-    return m_head_areas[head ? head-1 : 0].availableWorkspaceArea();
+    return m_head_areas[head ? head-1 : 0]->availableWorkspaceArea();
 }
 
 unsigned int BScreen::maxLeft(int head) const {
@@ -1548,7 +1552,7 @@ Strut *BScreen::requestStrut(int head, int left, int right, int top, int bottom)
 
     Strut* next = 0;
     for (int i = begin; i != end; i++) {
-        next = m_head_areas[i].requestStrut(i+1, left, right, top, bottom, next);
+        next = m_head_areas[i]->requestStrut(i+1, left, right, top, bottom, next);
     }
 
     return next;
@@ -1558,7 +1562,7 @@ void BScreen::clearStrut(Strut *str) {
     if (str->next())
         clearStrut(str->next());
     int head = str->head() ? str->head() - 1 : 0;
-    m_head_areas[head].clearStrut(str);
+    m_head_areas[head]->clearStrut(str);
     // str is invalid now
 }
 
@@ -1567,7 +1571,7 @@ void BScreen::updateAvailableWorkspaceArea() {
     bool updated = false;
 
     for (size_t i = 0; i < n; i++) {
-        updated = m_head_areas[i].updateAvailableWorkspaceArea() || updated;
+        updated = m_head_areas[i]->updateAvailableWorkspaceArea() || updated;
     }
 
     if (updated)
@@ -2128,6 +2132,9 @@ void BScreen::renderPosWindow() {
 }
 
 void BScreen::updateSize() {
+    // update xinerama layout
+    initXinerama();
+
     // force update geometry
     rootWindow().updateGeometry();
 
@@ -2187,6 +2194,8 @@ void BScreen::initXinerama() {
         cerr<<"BScreen::initXinerama(): dont have Xinerama"<<endl;
 #endif // DEBUG
         m_xinerama_avail = false;
+	if (m_xinerama_headinfo)
+	    delete [] m_xinerama_headinfo;
         m_xinerama_headinfo = 0;
         m_xinerama_num_heads = 0;
         return;
@@ -2199,6 +2208,8 @@ void BScreen::initXinerama() {
     XineramaScreenInfo *screen_info;
     int number;
     screen_info = XineramaQueryScreens(display, &number);
+    if (m_xinerama_headinfo)
+	delete [] m_xinerama_headinfo;
     m_xinerama_headinfo = new XineramaHeadInfo[number];
     m_xinerama_num_heads = number;
     for (int i=0; i < number; i++) {
@@ -2212,6 +2223,13 @@ void BScreen::initXinerama() {
     cerr<<"BScreen::initXinerama(): number of heads ="<<number<<endl;
 #endif // DEBUG
 
+    // We have to allocate additional HeadAreas, but never delete existing
+    // ones, it would just crash. -lis
+    int ha_num = numHeads() ? numHeads() : 1, ha_oldnum = m_head_areas.size();
+    m_head_areas.resize(ha_num);
+    for (int i = ha_oldnum; i < ha_num; i++)
+	m_head_areas[i] = new HeadArea();
+
 #else // XINERAMA
     // no xinerama
     m_xinerama_avail = false;
diff --git a/src/Screen.hh b/src/Screen.hh
index bf03ac6..ba550a7 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -492,7 +492,7 @@ private:
     int m_xinerama_num_heads;
     int m_xinerama_center_x, m_xinerama_center_y;
 
-    HeadArea *m_head_areas;
+    std::vector<HeadArea *> m_head_areas;
 
     struct XineramaHeadInfo {
         int x, y, width, height;        
-- 
1.4.4.4

