Here is a series of patches that came from frustration with bug #9955. The main idea was to have different mouse cursor when clicking would select a tabular row/column. This would make the feature much more discoverable.

0001: the infrastructure. I need to add a parameter BufferView to Inset::clickable

0002: implement clickable for InsetTabular. This is enough to make the magic happen. The only strange thing is that for column selection there is no margin above/below the tabular. I have used a margin inside the tabuar (6 pixels), but this may prove annoying. Testing will tell.

000[345]: when implementing 0001 I discovered that many display-related mutable variables in InsetCollapsable were not bv dependent, which is definitely bad (think split views). These patches fix that. I think this fixes #9756 and probably some other split-view bugs.

This patches are not for 2.2.0 (unless people ask for it). I think 0001+0002 can be safely backported to 2.2.x though; I am less sure about the other part, which requires testing, but it is not terribly risky IMO.

Comments welcome, as always.

JMarc
>From ac0c703133f1e1077a335e262ff7e967238b22b0 Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Tue, 2 Feb 2016 17:17:10 +0100
Subject: [PATCH 1/5] Pass a BufferView to Inset::clickable

---
 src/BufferView.cpp              |    2 +-
 src/insets/Inset.cpp            |    2 +-
 src/insets/Inset.h              |    2 +-
 src/insets/InsetCollapsable.cpp |    2 +-
 src/insets/InsetCollapsable.h   |    2 +-
 src/insets/InsetCommand.cpp     |    2 +-
 src/insets/InsetCommand.h       |    2 +-
 src/insets/InsetExternal.h      |    2 +-
 src/insets/InsetFloatList.h     |    2 +-
 src/insets/InsetGraphics.h      |    2 +-
 src/insets/InsetSpace.h         |    2 +-
 src/insets/InsetTOC.h           |    2 +-
 src/insets/InsetVSpace.h        |    2 +-
 13 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 81ebe79..fe5bd3e 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -2124,7 +2124,7 @@ void BufferView::updateHoveredInset() const
 	int const y = d->mouse_position_cache_.y_;
 	Inset const * covering_inset = getCoveringInset(buffer_.text(), x, y);
 
-	d->clickable_inset_ = covering_inset && covering_inset->clickable(x, y);
+	d->clickable_inset_ = covering_inset && covering_inset->clickable(*this, x, y);
 
 	if (covering_inset == d->last_inset_)
 		// Same inset, no need to do anything...
diff --git a/src/insets/Inset.cpp b/src/insets/Inset.cpp
index 75991cd..a0bbf32 100644
--- a/src/insets/Inset.cpp
+++ b/src/insets/Inset.cpp
@@ -350,7 +350,7 @@ void Inset::doDispatch(Cursor & cur, FuncRequest &cmd)
 		// if the derived inset did not explicitly handle mouse_release,
 		// we assume we request the settings dialog
 		if (!cur.selection() && cmd.button() == mouse_button::button1
-		    && clickable(cmd.x(), cmd.y()) && hasSettings()) {
+		    && clickable(cur.bv(), cmd.x(), cmd.y()) && hasSettings()) {
 			FuncRequest tmpcmd(LFUN_INSET_SETTINGS);
 			dispatch(cur, tmpcmd);
 		}
diff --git a/src/insets/Inset.h b/src/insets/Inset.h
index 96071fa..c413f9b 100644
--- a/src/insets/Inset.h
+++ b/src/insets/Inset.h
@@ -344,7 +344,7 @@ public:
 	// true for InsetTabular & InsetText
 	virtual bool isActive() const { return nargs() > 0; }
 	/// can we click at the specified position ?
-	virtual bool clickable(int, int) const { return false; }
+	virtual bool clickable(BufferView const &, int, int) const { return false; }
 	/// Move one cell backwards
 	virtual bool allowsCaptionVariation(std::string const &) const { return false; }
 
diff --git a/src/insets/InsetCollapsable.cpp b/src/insets/InsetCollapsable.cpp
index aeac8b3..f94d7fd 100644
--- a/src/insets/InsetCollapsable.cpp
+++ b/src/insets/InsetCollapsable.cpp
@@ -414,7 +414,7 @@ bool InsetCollapsable::hitButton(FuncRequest const & cmd) const
 }
 
 
-bool InsetCollapsable::clickable(int x, int y) const
+bool InsetCollapsable::clickable(BufferView const &, int x, int y) const
 {
 	FuncRequest cmd(LFUN_NOACTION, x, y, mouse_button::none);
 	return hitButton(cmd);
diff --git a/src/insets/InsetCollapsable.h b/src/insets/InsetCollapsable.h
index f2ce0ca..f24beb5 100644
--- a/src/insets/InsetCollapsable.h
+++ b/src/insets/InsetCollapsable.h
@@ -69,7 +69,7 @@ public:
 	///
 	bool hasSettings() const { return true; }
 	///
-	bool clickable(int x, int y) const;
+	bool clickable(BufferView const &, int x, int y) const;
 	/// can we go further down on mouse click?
 	bool descendable(BufferView const & bv) const;
 	///
diff --git a/src/insets/InsetCommand.cpp b/src/insets/InsetCommand.cpp
index dbbaed1..fcda3cd 100644
--- a/src/insets/InsetCommand.cpp
+++ b/src/insets/InsetCommand.cpp
@@ -94,7 +94,7 @@ InsetCommand::~InsetCommand()
 
 void InsetCommand::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-	button_.update(screenLabel(), editable() || clickable(0, 0));
+	button_.update(screenLabel(), editable() || clickable(*mi.base.bv, 0, 0));
 	button_.metrics(mi, dim);
 }
 
diff --git a/src/insets/InsetCommand.h b/src/insets/InsetCommand.h
index 1be72a8..39b1cbb 100644
--- a/src/insets/InsetCommand.h
+++ b/src/insets/InsetCommand.h
@@ -87,7 +87,7 @@ public:
 	///
 	bool setMouseHover(BufferView const * bv, bool mouse_hover) const;
 	///
-	bool clickable(int, int) const { return hasSettings(); }
+	bool clickable(BufferView const &, int, int) const { return hasSettings(); }
 	//@}
 
 protected:
diff --git a/src/insets/InsetExternal.h b/src/insets/InsetExternal.h
index 7513118..813e933 100644
--- a/src/insets/InsetExternal.h
+++ b/src/insets/InsetExternal.h
@@ -118,7 +118,7 @@ public:
 	///
 	bool setMouseHover(BufferView const * bv, bool mouse_hover) const;
 	///
-	bool clickable(int, int) const { return true; }
+	bool clickable(BufferView const &, int, int) const { return true; }
 	///
 	void addToToc(DocIterator const & di, bool output_active,
 				  UpdateType utype) const;
diff --git a/src/insets/InsetFloatList.h b/src/insets/InsetFloatList.h
index 58a7e23..32a0dd5 100644
--- a/src/insets/InsetFloatList.h
+++ b/src/insets/InsetFloatList.h
@@ -49,7 +49,7 @@ public:
 	///
 	void doDispatch(Cursor & cur, FuncRequest & cmd);
 	///
-	bool clickable(int, int) const { return true; }
+	bool clickable(BufferView const &, int, int) const { return true; }
 	///
 	void validate(LaTeXFeatures & features) const;
 	//@}
diff --git a/src/insets/InsetGraphics.h b/src/insets/InsetGraphics.h
index 3cf296f..5270f2b 100644
--- a/src/insets/InsetGraphics.h
+++ b/src/insets/InsetGraphics.h
@@ -53,7 +53,7 @@ public:
 
 	InsetGraphicsParams getParams() const { return params_;}
 	///
-	bool clickable(int, int) const { return true; }
+	bool clickable(BufferView const &, int, int) const { return true; }
 
 private:
 	///
diff --git a/src/insets/InsetSpace.h b/src/insets/InsetSpace.h
index 03ca7ae..a4fd615 100644
--- a/src/insets/InsetSpace.h
+++ b/src/insets/InsetSpace.h
@@ -139,7 +139,7 @@ public:
 	///
 	bool hasSettings() const { return true; }
 	///
-	bool clickable(int, int) const { return true; }
+	bool clickable(BufferView const &, int, int) const { return true; }
 	///
 	InsetCode lyxCode() const { return SPACE_CODE; }
 	/// does this inset try to use all available space (like \\hfill does)?
diff --git a/src/insets/InsetTOC.h b/src/insets/InsetTOC.h
index 074ad53..bd6ba17 100644
--- a/src/insets/InsetTOC.h
+++ b/src/insets/InsetTOC.h
@@ -49,7 +49,7 @@ public:
 	///
 	void doDispatch(Cursor & cur, FuncRequest & cmd);
 	///
-	bool clickable(int, int) const { return true; }
+	bool clickable(BufferView const &, int, int) const { return true; }
 	//@}
 
 	/// \name Static public methods obligated for InsetCommand derived classes
diff --git a/src/insets/InsetVSpace.h b/src/insets/InsetVSpace.h
index e94ebcd..21afbcd 100644
--- a/src/insets/InsetVSpace.h
+++ b/src/insets/InsetVSpace.h
@@ -32,7 +32,7 @@ public:
 	///
 	bool hasSettings() const { return true; }
 	///
-	bool clickable(int, int) const { return true; }
+	bool clickable(BufferView const &, int, int) const { return true; }
 	///
 	std::string contextMenuName() const;
 	///
-- 
1.7.9.5

>From 22e3ad48020663c0a94ef6b8821db708e321024e Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Tue, 2 Feb 2016 17:07:29 +0100
Subject: [PATCH 2/5] Change mouse cursor on tabular selection zones

This is done by implementing the clickable method. It is not possible yet to have the usual left and down arrows, because Qt does not implement them as far as I can see.

Factor the code that triggers row/column selection and fix the logic. Now it is possible to select also at the right of the tabular inset.
---
 src/insets/InsetTabular.cpp |   30 +++++++++++++++++++++++++-----
 src/insets/InsetTabular.h   |    7 +++++++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp
index 2d967bc..8f8275a 100644
--- a/src/insets/InsetTabular.cpp
+++ b/src/insets/InsetTabular.cpp
@@ -3951,6 +3951,29 @@ void InsetTabular::addToToc(DocIterator const & cpit, bool output_active,
 }
 
 
+bool InsetTabular::hitSelectRow(BufferView const & bv, int x) const
+{
+	int const x0 = xo(bv) + ADD_TO_TABULAR_WIDTH;
+	return x < x0 || x > x0 + tabular.width();
+}
+
+
+bool InsetTabular::hitSelectColumn(BufferView const & bv, int y) const
+{
+	int const y0 = yo(bv) - tabular.rowAscent(0) + offset_valign_;
+	// FIXME: using ADD_TO_TABULAR_WIDTH is not really correct since
+	// there is no margin added vertically to tabular insets.
+	// Howerver, it works for now.
+	return y < y0 + ADD_TO_TABULAR_WIDTH || y > y0 + tabular.height() - ADD_TO_TABULAR_WIDTH;
+}
+
+
+bool InsetTabular::clickable(BufferView const & bv, int x, int y) const
+{
+	return hitSelectRow(bv, x) || hitSelectColumn(bv, y);
+}
+
+
 void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
 	LYXERR(Debug::DEBUG, "# InsetTabular::doDispatch: cmd: " << cmd
@@ -3965,8 +3988,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 	case LFUN_MOUSE_PRESS: {
 		//lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl;
 		// select row
-		if (cmd.x() < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
-			|| cmd.x() > xo(cur.bv()) + tabular.width()) {
+		if (hitSelectRow(cur.bv(), cmd.x())) {
 			row_type r = rowFromY(cur, cmd.y());
 			cur.idx() = tabular.getFirstCellInRow(r);
 			cur.pit() = 0;
@@ -3981,9 +4003,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
 			break;
 		}
 		// select column
-		int const y0 = yo(cur.bv()) - tabular.rowAscent(0) + offset_valign_;
-		if (cmd.y() < y0 + ADD_TO_TABULAR_WIDTH
-			|| cmd.y() > y0 + tabular.height()) {
+		if (hitSelectColumn(cur.bv(), cmd.y())) {
 			col_type c = columnFromX(cur, cmd.x());
 			cur.idx() = tabular.cellIndex(0, c);
 			cur.pit() = 0;
diff --git a/src/insets/InsetTabular.h b/src/insets/InsetTabular.h
index 026489d..a0866fd 100644
--- a/src/insets/InsetTabular.h
+++ b/src/insets/InsetTabular.h
@@ -1004,6 +1004,13 @@ private:
 	Inset * clone() const { return new InsetTabular(*this); }
 
 	///
+	bool hitSelectRow(BufferView const & bv, int x) const;
+	///
+	bool hitSelectColumn(BufferView const & bv, int y) const;
+	///	Returns true if coordinates are on row/column selection zones
+	bool clickable(BufferView const &, int x, int y) const;
+
+	///
 	void drawCellLines(PainterInfo &, int x, int y, row_type row,
 			   idx_type cell) const;
 	///
-- 
1.7.9.5

>From cb07596777fbe38d571ced557acabb86636a7e65 Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Wed, 3 Feb 2016 10:42:01 +0100
Subject: [PATCH 3/5] whitespace only

---
 src/insets/InsetCollapsable.cpp |   16 ++++++++--------
 src/insets/InsetCollapsable.h   |    6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/insets/InsetCollapsable.cpp b/src/insets/InsetCollapsable.cpp
index f94d7fd..c4ca450 100644
--- a/src/insets/InsetCollapsable.cpp
+++ b/src/insets/InsetCollapsable.cpp
@@ -316,11 +316,11 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
 
 		const int xx1 = x + TEXT_TO_INSET_OFFSET - 1;
 		const int xx2 = x + textdim.wid - TEXT_TO_INSET_OFFSET + 1;
-		pi.pain.line(xx1, y + desc - 4, 
-			     xx1, y + desc, 
+		pi.pain.line(xx1, y + desc - 4,
+			     xx1, y + desc,
 			Color_foreground);
 		if (status_ == Open)
-			pi.pain.line(xx1, y + desc, 
+			pi.pain.line(xx1, y + desc,
 				xx2, y + desc,
 				Color_foreground);
 		else {
@@ -332,7 +332,7 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
 				xx2, y + desc,
 				Color_foreground);
 		}
-		pi.pain.line(x + textdim.wid - 3, y + desc, x + textdim.wid - 3, 
+		pi.pain.line(x + textdim.wid - 3, y + desc, x + textdim.wid - 3,
 			y + desc - 4, Color_foreground);
 
 		// the label below the text. Can be toggled.
@@ -454,8 +454,8 @@ Inset * InsetCollapsable::editXY(Cursor & cur, int x, int y)
 {
 	//lyxerr << "InsetCollapsable: edit xy" << endl;
 	if (geometry(cur.bv()) == ButtonOnly
-	 || (button_dim.contains(x, y) 
-	  && geometry(cur.bv()) != NoButton))
+		|| (button_dim.contains(x, y)
+			&& geometry(cur.bv()) != NoButton))
 		return this;
 	cur.push(*this);
 	return InsetText::editXY(cur, x, y);
@@ -508,7 +508,7 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
 			if (geometry(cur.bv()) != ButtonOnly)
 				InsetText::doDispatch(cur, cmd);
 			else
-				cur.undispatched();			
+				cur.undispatched();
 			break;
 		}
 		if (cmd.button() != mouse_button::button1) {
@@ -586,7 +586,7 @@ void InsetCollapsable::setLabel(docstring const & l)
 docstring const InsetCollapsable::buttonLabel(BufferView const & bv) const
 {
 	InsetLayout const & il = getLayout();
-	docstring const label = labelstring_.empty() ? 
+	docstring const label = labelstring_.empty() ?
 		translateIfPossible(il.labelstring()) : labelstring_;
 	if (!il.contentaslabel() || geometry(bv) != ButtonOnly)
 		return label;
diff --git a/src/insets/InsetCollapsable.h b/src/insets/InsetCollapsable.h
index f24beb5..e231ca0 100644
--- a/src/insets/InsetCollapsable.h
+++ b/src/insets/InsetCollapsable.h
@@ -79,7 +79,7 @@ public:
 	///
 	virtual docstring const buttonLabel(BufferView const &) const;
 	///
-	bool isOpen(BufferView const & bv) const 
+	bool isOpen(BufferView const & bv) const
 		{ return geometry(bv) != ButtonOnly; }
 	///
 	enum CollapseStatus {
@@ -90,7 +90,7 @@ public:
 	virtual void setStatus(Cursor & cur, CollapseStatus st);
 	///
 	CollapseStatus status(BufferView const & bv) const;
-	/** Of the old CollapseStatus we only keep the values  
+	/** Of the old CollapseStatus we only keep the values
 	 *  Open and Collapsed.
 	 * We define a list of possible inset decoration
 	 * styles, and a list of possible (concrete, visual)
@@ -152,7 +152,7 @@ protected:
 	///
 	void doDispatch(Cursor & cur, FuncRequest & cmd);
 	///
-	void edit(Cursor & cur, bool front, 
+	void edit(Cursor & cur, bool front,
 		EntryDirection entry_from = ENTRY_DIRECTION_IGNORE);
 	///
 	Inset * editXY(Cursor & cur, int x, int y);
-- 
1.7.9.5

>From 3c6d2f755d3058547e2021c2b61c345999dd68ee Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Wed, 3 Feb 2016 10:37:29 +0100
Subject: [PATCH 4/5] Make InsetCollapsable::button_dim_ bv-dependent

Make the button dimension, which is computed at draw time, dependent of the bufferview, like the other mutable members.

Rename it from button_dim to button_dim_, since it is private.

Get rid of the hitButton function.

This may improve the situation with split views, and in particular #9756.
---
 src/insets/InsetCollapsable.cpp |   46 +++++++++++++++++----------------------
 src/insets/InsetCollapsable.h   |   10 ++++-----
 2 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/src/insets/InsetCollapsable.cpp b/src/insets/InsetCollapsable.cpp
index c4ca450..6925d72 100644
--- a/src/insets/InsetCollapsable.cpp
+++ b/src/insets/InsetCollapsable.cpp
@@ -53,7 +53,7 @@ InsetCollapsable::InsetCollapsable(InsetCollapsable const & rhs)
 	: InsetText(rhs),
 	  status_(rhs.status_),
 	  labelstring_(rhs.labelstring_),
-	  button_dim(rhs.button_dim),
+	  button_dim_(rhs.button_dim_),
 	  openinlined_(rhs.openinlined_)
 {}
 
@@ -214,13 +214,12 @@ void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
 	case LeftButton:
 	case ButtonOnly:
 		if (hasFixedWidth()){
-			int const mindim = button_dim.x2 - button_dim.x1;
+			int const mindim = button_dim_[&bv].x2 - button_dim_[&bv].x1;
 			if (mi.base.textwidth < mindim)
 				mi.base.textwidth = mindim;
 		}
 		dim = dimensionCollapsed(bv);
-		if (geometry(bv) == TopButton 
-			  || geometry(bv) == LeftButton) {
+		if (geometry(bv) == TopButton || geometry(bv) == LeftButton) {
 			Dimension textdim;
 			InsetText::metrics(mi, textdim);
 			openinlined_ = (textdim.wid + dim.wid) < mi.base.textwidth;
@@ -265,20 +264,20 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
 	if (geometry(bv) == TopButton ||
 	    geometry(bv) == LeftButton ||
 	    geometry(bv) == ButtonOnly) {
-		button_dim.x1 = x + 0;
-		button_dim.x2 = x + dimc.width();
-		button_dim.y1 = y - dimc.asc;
-		button_dim.y2 = y + dimc.des;
+		button_dim_[&bv].x1 = x + 0;
+		button_dim_[&bv].x2 = x + dimc.width();
+		button_dim_[&bv].y1 = y - dimc.asc;
+		button_dim_[&bv].y2 = y + dimc.des;
 
 		FontInfo labelfont = getLabelfont();
 		labelfont.setColor(labelColor());
 		pi.pain.buttonText(x, y, buttonLabel(bv), labelfont,
 			mouse_hover_[&bv]);
 	} else {
-		button_dim.x1 = 0;
-		button_dim.y1 = 0;
-		button_dim.x2 = 0;
-		button_dim.y2 = 0;
+		button_dim_[&bv].x1 = 0;
+		button_dim_[&bv].y1 = 0;
+		button_dim_[&bv].x2 = 0;
+		button_dim_[&bv].y2 = 0;
 	}
 
 	Dimension const textdim = InsetText::dimension(bv);
@@ -408,16 +407,9 @@ bool InsetCollapsable::descendable(BufferView const & bv) const
 }
 
 
-bool InsetCollapsable::hitButton(FuncRequest const & cmd) const
+bool InsetCollapsable::clickable(BufferView const & bv, int x, int y) const
 {
-	return button_dim.contains(cmd.x(), cmd.y());
-}
-
-
-bool InsetCollapsable::clickable(BufferView const &, int x, int y) const
-{
-	FuncRequest cmd(LFUN_NOACTION, x, y, mouse_button::none);
-	return hitButton(cmd);
+	return button_dim_[&bv].contains(x, y);
 }
 
 
@@ -454,8 +446,8 @@ Inset * InsetCollapsable::editXY(Cursor & cur, int x, int y)
 {
 	//lyxerr << "InsetCollapsable: edit xy" << endl;
 	if (geometry(cur.bv()) == ButtonOnly
-		|| (button_dim.contains(x, y)
-			&& geometry(cur.bv()) != NoButton))
+	    || (button_dim_[&cur.bv()].contains(x, y)
+	        && geometry(cur.bv()) != NoButton))
 		return this;
 	cur.push(*this);
 	return InsetText::editXY(cur, x, y);
@@ -467,9 +459,11 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
 	//lyxerr << "InsetCollapsable::doDispatch (begin): cmd: " << cmd
 	//	<< " cur: " << cur << " bvcur: " << cur.bv().cursor() << endl;
 
+	bool const hitButton = clickable(cur.bv(), cmd.x(), cmd.y());
+
 	switch (cmd.action()) {
 	case LFUN_MOUSE_PRESS:
-		if (hitButton(cmd)) {
+		if (hitButton) {
 			switch (cmd.button()) {
 			case mouse_button::button1:
 			case mouse_button::button3:
@@ -494,7 +488,7 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
 	case LFUN_MOUSE_MOTION:
 	case LFUN_MOUSE_DOUBLE:
 	case LFUN_MOUSE_TRIPLE:
-		if (hitButton(cmd)) 
+		if (hitButton)
 			cur.noScreenUpdate();
 		else if (geometry(cur.bv()) != ButtonOnly)
 			InsetText::doDispatch(cur, cmd);
@@ -503,7 +497,7 @@ void InsetCollapsable::doDispatch(Cursor & cur, FuncRequest & cmd)
 		break;
 
 	case LFUN_MOUSE_RELEASE:
-		if (!hitButton(cmd)) {
+		if (!hitButton) {
 			// The mouse click has to be within the inset!
 			if (geometry(cur.bv()) != ButtonOnly)
 				InsetText::doDispatch(cur, cmd);
diff --git a/src/insets/InsetCollapsable.h b/src/insets/InsetCollapsable.h
index e231ca0..1f7b798 100644
--- a/src/insets/InsetCollapsable.h
+++ b/src/insets/InsetCollapsable.h
@@ -58,17 +58,15 @@ public:
 	/// return x,y of given position relative to the inset's baseline
 	void cursorPos(BufferView const & bv, CursorSlice const & sl,
 		bool boundary, int & x, int & y) const;
-	/// Returns true if (mouse) action is over the inset's button.
-	/// Always returns false when the inset does not have a
-	/// button.
-	bool hitButton(FuncRequest const &) const;
 	///
 	docstring const getNewLabel(docstring const & l) const;
 	///
 	bool editable() const;
 	///
 	bool hasSettings() const { return true; }
-	///
+	///	Returns true if coordinates are over the inset's button.
+	/// Always returns false when the inset does not have a
+	/// button.
 	bool clickable(BufferView const &, int x, int y) const;
 	/// can we go further down on mouse click?
 	bool descendable(BufferView const & bv) const;
@@ -164,7 +162,7 @@ private:
 	///
 	docstring labelstring_;
 	///
-	mutable Box button_dim;
+	mutable std::map<BufferView const *, Box> button_dim_;
 	/// a substatus of the Open status, determined automatically in metrics
 	mutable bool openinlined_;
 	/// the inset will automatically open when the cursor is inside. This is
-- 
1.7.9.5

>From ba23f7565955a11e800ee978ffd1106caa3794c0 Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Wed, 3 Feb 2016 12:20:18 +0100
Subject: [PATCH 5/5] Make InsetCollapsable::openinlined_ bv-dependent

This is required when several bufferviews exist for the same inset (see bug #9756).

Remove the bv-independent geometry() method and implement editable() explicitely instead.
---
 src/insets/InsetCollapsable.cpp |   40 +++++++++++----------------------------
 src/insets/InsetCollapsable.h   |    4 +---
 2 files changed, 12 insertions(+), 32 deletions(-)

diff --git a/src/insets/InsetCollapsable.cpp b/src/insets/InsetCollapsable.cpp
index 6925d72..b29bf04 100644
--- a/src/insets/InsetCollapsable.cpp
+++ b/src/insets/InsetCollapsable.cpp
@@ -40,7 +40,7 @@ using namespace std;
 namespace lyx {
 
 InsetCollapsable::InsetCollapsable(Buffer * buf, InsetText::UsePlain ltype)
-	: InsetText(buf, ltype), status_(Open), openinlined_(false)
+	: InsetText(buf, ltype), status_(Open)
 {
 	setDrawFrame(true);
 	setFrameColor(Color_collapsableframe);
@@ -81,7 +81,7 @@ InsetCollapsable::Geometry InsetCollapsable::geometry(BufferView const & bv) con
 	switch (decoration()) {
 	case InsetLayout::CLASSIC:
 		if (status(bv) == Open)
-			return openinlined_ ? LeftButton : TopButton;
+			return openinlined_[&bv] ? LeftButton : TopButton;
 		return ButtonOnly;
 
 	case InsetLayout::MINIMALISTIC:
@@ -100,30 +100,6 @@ InsetCollapsable::Geometry InsetCollapsable::geometry(BufferView const & bv) con
 }
 
 
-InsetCollapsable::Geometry InsetCollapsable::geometry() const
-{
-	switch (decoration()) {
-	case InsetLayout::CLASSIC:
-		if (status_ == Open)
-			return openinlined_ ? LeftButton : TopButton;
-		return ButtonOnly;
-
-	case InsetLayout::MINIMALISTIC:
-		return status_ == Open ? NoButton : ButtonOnly ;
-
-	case InsetLayout::CONGLOMERATE:
-		return status_ == Open ? SubLabel : Corners ;
-
-	case InsetLayout::DEFAULT:
-		break; // this shouldn't happen
-	}
-
-	// dummy return value to shut down a warning,
-	// this is dead code.
-	return NoButton;
-}
-
-
 docstring InsetCollapsable::toolTip(BufferView const & bv, int x, int y) const
 {
 	Dimension const dim = dimensionCollapsed(bv);
@@ -222,8 +198,8 @@ void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
 		if (geometry(bv) == TopButton || geometry(bv) == LeftButton) {
 			Dimension textdim;
 			InsetText::metrics(mi, textdim);
-			openinlined_ = (textdim.wid + dim.wid) < mi.base.textwidth;
-			if (openinlined_) {
+			openinlined_[&bv] = (textdim.wid + dim.wid) < mi.base.textwidth;
+			if (openinlined_[&bv]) {
 				// Correct for button width.
 				dim.wid += textdim.wid;
 				dim.des = max(dim.des - textdim.asc + dim.asc, textdim.des);
@@ -397,7 +373,13 @@ void InsetCollapsable::cursorPos(BufferView const & bv,
 
 bool InsetCollapsable::editable() const
 {
-	return geometry() != ButtonOnly;
+	switch (decoration()) {
+	case InsetLayout::CLASSIC:
+	case InsetLayout::MINIMALISTIC:
+		return status_ != Open;
+	default:
+		return true;
+	}
 }
 
 
diff --git a/src/insets/InsetCollapsable.h b/src/insets/InsetCollapsable.h
index 1f7b798..160f6cd 100644
--- a/src/insets/InsetCollapsable.h
+++ b/src/insets/InsetCollapsable.h
@@ -126,8 +126,6 @@ public:
 	/// (status_), auto_open_[BufferView] and openinlined_,
 	/// and of course decoration().
 	Geometry geometry(BufferView const & bv) const;
-	/// Returns the geometry disregarding auto_open_
-	Geometry geometry() const;
 	///
 	bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
 	///
@@ -164,7 +162,7 @@ private:
 	///
 	mutable std::map<BufferView const *, Box> button_dim_;
 	/// a substatus of the Open status, determined automatically in metrics
-	mutable bool openinlined_;
+	mutable std::map<BufferView const *, bool> openinlined_;
 	/// the inset will automatically open when the cursor is inside. This is
 	/// dependent on the bufferview, compare with MathMacro::editing_.
 	mutable std::map<BufferView const *, bool> auto_open_;
-- 
1.7.9.5

Reply via email to