public inbox for cygwin-xfree@sourceware.org
help / color / mirror / Atom feed
From: David Stacey <drstacey@tiscali.co.uk>
To: cygwin-xfree@cygwin.com
Subject: 64-bit Clipboard troubles
Date: Sun, 09 Jun 2013 18:59:00 -0000	[thread overview]
Message-ID: <51B4D075.3050001@tiscali.co.uk> (raw)

[-- Attachment #1: Type: text/plain, Size: 3203 bytes --]

I am trying to package keepassx for 64-bit Cygwin, and have noticed a 
difference between the way the clipboard functions under 32-bit and 
64-bit Cygwin/X. Essentially, keepassx is an encrypted password database 
that copies your username and password to the clipboard. Then, you can 
paste these into a web site (say) to log in.

When I run keepassx (both 32-bit and 64-bit builds) using the 32-bit 
version of XWin, keepassx copies the username and password to the 
clipboard, and these can be pasted into a native Windows web browser 
(e.g. Firefox). However, when I run keepassx (again, both 32-bit and 
64-bit builds) using the 64-bit version of XWin, the procedure breaks: I 
instruct keepassx to copy to the clipboard, but when I paste in the web 
browser, no test is pasted.

I attempted to write a testcase programme to access the clipboard in 
various ways. The programme doesn't work as I had quite intended (which 
is almost certainly down to my limited understanding of how the 
clipboard works in X), but it does highlight differences between 32-bit 
and 64-bit XWin, so I have attached it in case it is useful.

The testcase programme reads and writes to the clipboard using two 
techniques - either through Qt4 (identical to the code used in keepassx) 
or by accessing /dev/clipboard. The difference comes when writing to the 
clipboard by writing to /dev/clipboard and then reading it back using 
Qt4 - under 32-bit XWin this succeeds (i.e. the correct text is read 
back), but under 64-bit XWin an empty string is read.

I mentioned that my testcase programme doesn't quite work as I intended: 
writing to the clipboard using Qt4 and reading it back by reading 
/dev/clipboard fails when using both 32-bit and 64-bit XWin. I don't 
understand why, but this is probably down to my own limited 
understanding of the clipboard in X.

Here is my environment: I'm running Windows 7 Ultimate x64 SP1.
32-bit Cygwin: Qt4-4.8.4-2 with xorg-server-1.14.1-1
64-bit Cygwin: Qt4-4.8.4-3 with xorg-server-1.14.1-1
The two Cygwin installations are installed side-by-side.

The 32-bit build of keepassx can be found in your favourite Cygwin 
mirror; if you need the 64-bit build then you can download it here:

BASEURL=http://dl.dropbox.com/sh/7y1yn4whbyho9a7
wget --no-check-certificate --no-host-directories --force-directories 
--cut-dirs=6 \
${BASEURL}/gMetoiuG3_/64bit/release/KDE/keepassx/keepassx-0.4.3-1-src.tar.bz2 
\
${BASEURL}/faOgOyuoYS/64bit/release/KDE/keepassx/keepassx-0.4.3-1.tar.bz2 \
${BASEURL}/xaqPOGFz3J/64bit/release/KDE/keepassx/setup.hint \
${BASEURL}/U82Dz9jF1S/64bit/release/KDE/keepassx/keepassx-debuginfo/keepassx-debuginfo-0.4.3-1.tar.bz2 
\
${BASEURL}/J4n6_izWKV/64bit/release/KDE/keepassx/keepassx-debuginfo/setup.hint

As the behaviour is different depending on whether I start 'XWin 
-multiwindow' on 32-bit or 64-bit Cygwin, I am posting here. If this is 
nothing to do with the xfree list then please accept my apologies and I 
will take the discussion to the main Cygwin list.

Apologies also for the length of the post, but hopefully there's enough 
information here to help to track down the cause of the problem.

Many thanks in advance for your help,

Dave.


[-- Attachment #2: qt4_clip.cpp --]
[-- Type: text/x-c++src, Size: 4397 bytes --]

// Compile: g++ -I/usr/include/qt4 -L/usr/lib/qt4/lib -o qt4_clip qt4_clip.cpp -lQtGui -lQtCore
#include <QtCore/QString>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <fstream>
#include <iostream>
#include <string>
#include <unistd.h>

// Abstract class to define a generic clipboard accessor.
class CClipboardAccess
{
public:
	explicit CClipboardAccess(const std::string &name) : Name(name) {}
	virtual ~CClipboardAccess() {}
	inline const std::string& GetName() const { return this->Name; }

	virtual void ClearClipboard() const = 0;
	virtual void SetClipboard(const std::string &str) const = 0;
	virtual std::string GetClipboard() const = 0;

private:
	std::string Name;
};

// A class to access the clipboard using the Qt QClipboard.
class CQtClipboardAccess : public CClipboardAccess
{
public:
	explicit CQtClipboardAccess(QApplication &app) : CClipboardAccess("QClipboard"), pApp(&app), pClip(QApplication::clipboard()) {}
	virtual ~CQtClipboardAccess() {}

	virtual void ClearClipboard() const
	{
		this->pApp->processEvents();
		this->pClip->clear(QClipboard::Clipboard);
		if (this->pClip->supportsSelection())
			this->pClip->clear(QClipboard::Selection);
	}

	virtual void SetClipboard(const std::string &str) const
	{
		this->pApp->processEvents();
		this->pClip->setText(str.c_str(), QClipboard::Clipboard);
		if (this->pClip->supportsSelection())
			this->pClip->setText(str.c_str(), QClipboard::Selection);
	}

	virtual std::string GetClipboard() const
	{
		this->pApp->processEvents();
		return this->pClip->text(QClipboard::Clipboard).toStdString();
	}

private:
	QApplication *pApp;
	QClipboard *pClip;
};

// A class to access the clipboard by reading / writing to '/dev/clipboard'.
class CCygwinClipboardAccess : public CClipboardAccess
{
public:
	CCygwinClipboardAccess() : CClipboardAccess("/dev/clipboard") {}
	virtual ~CCygwinClipboardAccess() {}

	virtual void ClearClipboard() const
	{
		this->SetClipboard("");
	}

	virtual void SetClipboard(const std::string &str) const
	{
		std::ofstream out(this->GetName().c_str());
		if (!out)
			std::cerr << "Unable to write to '" << this->GetName() << "'." << std::endl;
		else
			out << str;
	}

	virtual std::string GetClipboard() const
	{
		std::string line;
		std::ifstream in(this->GetName().c_str());
		if (!in)
			std::cerr << "Unable to read '" << this->GetName() << "'." << std::endl;
		else
			std::getline(in, line);
		return line;
	}
};

class CTest : public QApplication
{
public:
	CTest(int argc, char **pargv) : QApplication(argc, pargv) {}
	virtual ~CTest() {}

	void GoTest()
	{
		CQtClipboardAccess qt_clip(*this);
		CCygwinClipboardAccess cygwin_clip;

		// The tests.
		//
		// With 64-bit XWin, test 3 always fails, but for 32-bit XWin the same test passes.
		// This is true, irrespective of whether this code is compiled and run from 32-bit Cygwin or 64-bit Cygwin.
		//
		// Test 2 always fails, but I don't understand why.
		// Tests 1 and 4 always pass.
		this->RunTest(qt_clip,     qt_clip,     "Mary had a little lamb");
		this->RunTest(qt_clip,     cygwin_clip, "Whose fleece was as white as snow");
		this->RunTest(cygwin_clip, qt_clip,     "And everywhere that Mary went");
		this->RunTest(cygwin_clip, cygwin_clip, "The lamb was sure to go");
	}

private:
	// Procedure to run a test.
	// The string in 'str' is written to the clipboard using 'write'.
	// Then the clipboard is read using 'read'.
	// The string read should match 'str', i.e. we read back from the clipboard the same string we wrote to it.
	void RunTest(const CClipboardAccess &write, const CClipboardAccess &read, const std::string &str)
	{
		static unsigned int count = 0;
		std::cout << std::endl << "TEST " << (++count)
		          << ": Write using " << write.GetName()
				  << ", read using " << read.GetName() << '.' << std::endl;

		write.ClearClipboard();
		sleep(1);
		read.ClearClipboard();
		sleep(1);

		std::cout << ">>> Setting " << write.GetName() << " to '" << str << "'." << std::endl;
		write.SetClipboard(str);
		sleep(1);
		const std::string result = read.GetClipboard();
		std::cout << ">>> Read " << read.GetName() << " = '" << result << "'." << std::endl;

		if (result == str)
			std::cout << ">>> OK - strings match." << std::endl;
		else
			std::cout << "*** FAILED." << std::endl;
	}
};

int main(int argc, char **pargv)
{
	CTest test(argc, pargv);
	test.GoTest();
	return 0;
}


[-- Attachment #3: Type: text/plain, Size: 223 bytes --]

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://x.cygwin.com/docs/
FAQ:                   http://x.cygwin.com/docs/faq/

             reply	other threads:[~2013-06-09 18:59 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-09 18:59 David Stacey [this message]
2013-06-10 13:30 ` Jon TURNEY
2013-06-10 21:39   ` David Stacey
2013-06-21 12:33     ` Jon TURNEY
2013-06-21 18:02       ` David Stacey
2013-09-22  2:39       ` Clipboard periodically breaks Matt D.
2013-09-22  3:11         ` Matt D.
     [not found]         ` <524454A6.8030503@dronecode.org.uk>
2013-09-27  0:35           ` Matt D.
2013-10-21 14:46             ` Reinier Post
2013-10-21 22:37               ` Matt D.
2013-11-21 17:51               ` Jon TURNEY

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51B4D075.3050001@tiscali.co.uk \
    --to=drstacey@tiscali.co.uk \
    --cc=cygwin-xfree@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).