Commits

equalsraf  committed a3ae08b

Refactor painting and input event handling

- Stop using a pixmap as canvas to paint the widget
instead paint directly on the widget
- Keep a event queue for calls to some functions
in VimWrapper - this prevents some events from being
passed to Vim when we only want to process input
pending events, even if they are not input.
- QVimShell now inherits from VimWrapper.
- VimWrapper now has processEvents() method that
implements the behaviour previously seen in
gui_mch_wait_for_char - and that of the regular
QApplication::processEvents().
* We sometimes crash when resizing the window - if
mainwindow dock animations are on - for now I'm
disabling this.
* Issue#68

  • Participants
  • Parent commits 5125d03

Comments (0)

Files changed (9)

File src/Makefile

 			qt/qvimshell.cpp qt/mainwindow.cpp qt/vimaction.cpp qt/scrollarea.cpp \
 			qt/fontdialog.cpp \
 			qt/colortable.cpp \
-			qt/vimwrapper.cpp qt/tabbar.cpp qt/vimscrollbar.cpp
+			qt/vimwrapper.cpp qt/tabbar.cpp qt/vimscrollbar.cpp \
+			qt/vimevents.cpp
 QT_OBJ	= objects/gui.o objects/gui_qt.o \
 			objects/pty.o objects/gui_beval.o \
 			objects/mainwindow.o objects/qvimshell.o objects/vimaction.o objects/qtresources.o \
 			objects/colortable.o \
 			objects/scrollarea.o objects/fontdialog.o objects/vimwrapper.o \
+			objects/vimevents.o \
 			objects/tabbar.o objects/vimscrollbar.o
 
 QT_DEFS	= -DFEAT_GUI_QT $(NARROW_PROTO) -Iqt -I. $(QT_INCPATH)
 	$(CXX) $(ALL_CFLAGS) -o $@ -c qt/fontdialog.cpp
 
 objects/vimwrapper.o: qt/vimwrapper.cpp
-	$(MOC) qt/vimwrapper.h > vimwrapper.moc
 	$(CXX) $(ALL_CFLAGS) -o $@ -c qt/vimwrapper.cpp
 
+objects/vimevents.o: qt/vimevents.cpp
+	$(CXX) $(ALL_CFLAGS) -o $@ -c qt/vimevents.cpp
+
 objects/tabbar.o: qt/tabbar.cpp
 	$(MOC) qt/tabbar.h > tabbar.moc
 	$(CXX) $(ALL_CFLAGS) -o $@ -c qt/tabbar.cpp

File src/gui_qt.cpp

 #include <QToolBar>
 #include <QFileDialog>
 #include <QPushButton>
+#include <QTimer>
 
 #include "qvimshell.h"
 #include "mainwindow.h"
 		return OK;
 	}
 
-	if ( wtime == -1 ) {
-		QApplication::processEvents( QEventLoop::WaitForMoreEvents);
-		return OK;
-	} else {
-		QTime t;
-		t.start();
-		do {
-			QApplication::processEvents( QEventLoop::WaitForMoreEvents);
-			if (!vim_is_input_buf_empty()) {
-				return OK;
-			}
-		} while( t.elapsed() < wtime );
-	}
-
-	return FAIL;
+	return vimshell->processEvents(wtime, true);
 }
 
 /**
 void
 gui_mch_update()
 {
-	if ( QApplication::hasPendingEvents() ) {
-		QApplication::processEvents();
-	}
+	vimshell->processEvents();
 }
 
 
 void
 gui_mch_flush()
 {
-	// Is this necessary?
-	QApplication::flush();
+	vimshell->processEvents(0, true);
 }
 
 /**
 void
 gui_mch_clear_all()
 {
-	PaintOperation op;
-	op.type = CLEARALL;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::CLEARALL;
 	op.color = VimWrapper::fromColor(gui.back_pixel);
 	vimshell->queuePaintOp(op);
 }
 {
 	QRect rect = VimWrapper::mapBlock(row1, col1, row2, col2); 
 
-	PaintOperation op;
-	op.type = FILLRECT;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::FILLRECT;
 	op.color = VimWrapper::fromColor(gui.back_pixel);
 	op.rect = rect;
 	vimshell->queuePaintOp(op);
 	br.setX(vimshell->width());
 	br.setY(vimshell->height());
 
-	PaintOperation op;
-	op.type = FILLRECT;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::FILLRECT;
 	op.color = VimWrapper::fromColor(gui.back_pixel);
 	op.rect = QRect(tl, br);
 	vimshell->queuePaintOp(op);
 	QRect scrollRect = VimWrapper::mapBlock(row, gui.scroll_region_left, 
 					gui.scroll_region_bot, gui.scroll_region_right);
 
-	PaintOperation op1;
-	op1.type = SCROLLRECT;
+	QVimShell::PaintOperation op1;
+	op1.type = QVimShell::SCROLLRECT;
 	op1.rect = scrollRect;
 	op1.pos = QPoint(0, num_lines*gui.char_height);
 	op1.color = VimWrapper::fromColor(gui.back_pixel);
 	QRect scrollRect = VimWrapper::mapBlock(row, gui.scroll_region_left, 
 					gui.scroll_region_bot, gui.scroll_region_right);
 
-	PaintOperation op;
-	op.type = SCROLLRECT;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::SCROLLRECT;
 	op.rect = scrollRect;
 	op.pos = QPoint(0, -num_lines*gui.char_height);
 	op.color = VimWrapper::fromColor(gui.back_pixel);
 {
 	QRect rect = VimWrapper::mapBlock(row, col, row+nr-1, col +nc-1);
 
-	PaintOperation op;
-	op.type = INVERTRECT;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::INVERTRECT;
 	op.rect = rect;
 	vimshell->queuePaintOp(op);
 }
 			FILL_Y(gui.row)+gui.char_height-2);
 	QRect rect(tl, br);
 
-	PaintOperation op;
-	op.type = DRAWRECT;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::DRAWRECT;
 	op.rect = rect;
 	op.color = VimWrapper::fromColor(color);
 	vimshell->queuePaintOp(op);
 
 	QRect rect( x, y, w, h);
 
-	PaintOperation op;
-	op.type = FILLRECT;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::FILLRECT;
 	op.rect = rect;
 	op.color = VimWrapper::fromColor(color);
 	vimshell->queuePaintOp(op);
 		// Do we need to do anything?
 	} else {
 		// Fill in the background
-		PaintOperation op;
-		op.type = FILLRECT;
+		QVimShell::PaintOperation op;
+		op.type = QVimShell::FILLRECT;
 		op.rect = rect;
 		op.color = backgroundColor;
 		vimshell->queuePaintOp(op);
 
 	// Remove upper linespace from rect
 	QRect rect_text( pos.x(), pos.y() + p_linespace/2, gui.char_width*cellwidth, gui.char_height);
-	PaintOperation op;
-	op.type = DRAWSTRING;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::DRAWSTRING;
 	op.font = f;
 	op.rect = rect_text;
 	op.str = str;
 	op.color = foregroundColor;
 	op.undercurl = flags & DRAW_UNDERC;
-	if ( op.undercurl ) { // FIXME: Refactor PaintOperation
+	if ( op.undercurl ) { // FIXME: Refactor QVimShell::PaintOperation
 		op.curlcolor = specialColor;
 	}
 
 	}
 
 	QPoint pos = VimWrapper::mapText(row, col);
-	PaintOperation op;
-	op.type = DRAWSIGN;
+	QVimShell::PaintOperation op;
+	op.type = QVimShell::DRAWSIGN;
 	op.pos = pos;
 	op.sign = icon->pixmap( VimWrapper::charWidth()*2, VimWrapper::charHeight() );
 	op.rect = QRect(pos, QSize(VimWrapper::charWidth()*2, VimWrapper::charHeight()));

File src/qt/mainwindow.cpp

 	setWindowIcon(QIcon(":/icons/vim-qt.png"));
 	setContextMenuPolicy(Qt::PreventContextMenu);
 
+	// We sometimes crash if this is on
+	setAnimated(false);
+
 	// Menu
 	menutoolbar = addToolBar("Menu");
 	menutoolbar->setObjectName("menu");

File src/qt/qvimshell.cpp

 	setAttribute(Qt::WA_KeyCompression, true);
 	setAttribute(Qt::WA_InputMethodEnabled, true);
 	setAttribute(Qt::WA_OpaquePaintEvent, true);
+	setAutoFillBackground(true);
 	setAcceptDrops(true);
 	setMouseTracking(true);
 }
 void QVimShell::setBackground(const QColor color)
 {
 	m_background = color;
+	QPalette p = palette();
+	p.setColor(QPalette::Window, color);
+	setPalette(p);
 	emit backgroundColorChanged(m_background);
 }
 
 void QVimShell::switchTab(int idx)
 {
-	vim.sendTablineEvent(idx);
+	sendTablineEvent(idx);
 }
 
 void QVimShell::closeTab(int idx)
 {
-	vim.sendTablineMenuEvent(idx, TABLINE_MENU_CLOSE);
+	sendTablineMenuEvent(idx, TABLINE_MENU_CLOSE);
 }
 
 
 
 void QVimShell::resizeEvent(QResizeEvent *ev)
 {
-	if ( canvas.isNull() ) {
-		QPixmap newCanvas = QPixmap( ev->size() );
-		newCanvas.fill(background());
-		canvas = newCanvas;
-	} else {
-		// Keep old contents
-		QPixmap old = canvas.copy(QRect(QPoint(0,0), ev->size()));
-		canvas = QPixmap( ev->size() );
-		canvas.fill(background()); // FIXME: please optimise me
-
-		{
-		QPainter p(&canvas);
-		p.drawPixmap(QPoint(0,0), old);
-		}
-	}
-
 	update();
-	vim.guiResizeShell(ev->size().width(), ev->size().height());
+	guiResizeShell(ev->size().width(), ev->size().height());
 }
 
 /**
 
 void QVimShell::close()
 {
-	vim.guiShellClosed();
+	guiShellClosed();
 }
 
 void QVimShell::closeEvent(QCloseEvent *event)
 
 void QVimShell::flushPaintOps()
 {
-	QPainter painter(&canvas);
+	QPainter painter(this);
 	while ( !paintOps.isEmpty() ) {
 		painter.save();
 
 		PaintOperation op = paintOps.dequeue();
 		switch( op.type ) {
 		case CLEARALL:
-			painter.fillRect(canvas.rect(), op.color);
+			painter.fillRect(rect(), op.color);
 			break;
 		case FILLRECT:
 			painter.fillRect(op.rect, op.color);
 			painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
 			break;
 		case SCROLLRECT:
-			painter.restore();
-			painter.end();
-
-			QRegion exposed;
-			canvas.scroll(op.pos.x(), op.pos.y(),
-			 	op.rect, &exposed);
+			// We only support vertical scroll
+			// i.e. op.pos.x() is ignored
 
-			painter.begin(&canvas);
-			painter.fillRect(exposed.boundingRect(), op.color);
-			continue; // exception, skip painter restore
+			int top;
+			if ( op.pos.y() >= 0 ) {
+				top = op.rect.top();
+			} else {
+				top = op.rect.bottom() + op.pos.y();
+			}
+			QRect exposed(op.rect.left(), top, op.rect.width(), qAbs(op.pos.y()));
+			scroll(op.pos.x(), op.pos.y(), op.rect);
+			painter.fillRect(exposed, op.color);
+			break;
 		}
 
 		painter.restore();
 
 void QVimShell::paintEvent ( QPaintEvent *ev )
 {
+	QWidget::paintEvent(ev);
 	flushPaintOps();
-
-	QPainter realpainter(this);
-	foreach(const QRect r, ev->region().rects()) {
-		realpainter.drawPixmap( r, canvas, r);
-	}
 }
 
 //
 
 	if ( ev->buttons() ) {
 		int_u vmod = vimMouseModifiers(QApplication::keyboardModifiers());
-		vim.guiSendMouseEvent(MOUSE_DRAG, ev->pos().x(),
+		guiSendMouseEvent(MOUSE_DRAG, ev->pos().x(),
 					  ev->pos().y(), FALSE, vmod);
 	} else {
-		vim.guiMouseMoved(ev->pos().x(), ev->pos().y());
+		guiMouseMoved(ev->pos().x(), ev->pos().y());
 	}
 }
 
 
 	int_u vmod = vimMouseModifiers(QApplication::keyboardModifiers());
 
-	vim.guiSendMouseEvent(but, ev->pos().x(),
+	guiSendMouseEvent(but, ev->pos().x(),
 					  ev->pos().y(), repeat, vmod);
 }
 
 void QVimShell::mouseReleaseEvent(QMouseEvent *ev)
 {
 	int_u vmod = vimMouseModifiers(QApplication::keyboardModifiers());
-	vim.guiSendMouseEvent(MOUSE_RELEASE, ev->pos().x(),
+	guiSendMouseEvent(MOUSE_RELEASE, ev->pos().x(),
 					  ev->pos().y(), FALSE, vmod);
 }
 
 void QVimShell::wheelEvent(QWheelEvent *ev)
 {
 	int_u vmod = vimMouseModifiers(QApplication::keyboardModifiers());
-	vim.guiSendMouseEvent((ev->delta() > 0) ? MOUSE_4 : MOUSE_5,
+	guiSendMouseEvent((ev->delta() > 0) ? MOUSE_4 : MOUSE_5,
 					    ev->pos().x(), ev->pos().y(), FALSE, vmod);
 }
 
 		if ( urls.size() == 0 ) {
 			return;
 		}
-		vim.guiHandleDrop(ev->pos().x(), ev->pos().y(), 0, urls);
+		guiHandleDrop(ev->pos(), 0, urls);
 
 	} else {
-		QByteArray text = VimWrapper::convertTo(ev->mimeData()->text());
-		dnd_yank_drag_data( (char_u*)text.data(), text.size());
-
-		char_u buf[3] = {CSI, KS_EXTRA, (char_u)KE_DROP};
-		add_to_input_buf(buf, 3);
+		guiHandleDropText(ev->mimeData()->text());
 	}
 	ev->acceptProposedAction();
 }
 	// mousehide - show mouse pointer
 	restoreCursor();
 
-	vim.guiFocusChanged(TRUE);
+	guiFocusChanged(TRUE);
 	QWidget::focusInEvent(ev);
 	update();
 }
 
 void QVimShell::focusOutEvent(QFocusEvent *ev)
 {
-	vim.guiFocusChanged(FALSE);
+	guiFocusChanged(FALSE);
 	QWidget::focusOutEvent(ev);
 	update();
 }
 void QVimShell::cursorOff()
 {
 	blinkState = BLINK_OFF;
-	vim.undrawCursor();
+	undrawCursor();
 }
 
 void QVimShell::cursorOn()
 {
 	blinkState = BLINK_ON;
-	vim.updateCursor(true, false);
+	updateCursor(true, false);
 }

File src/qt/qvimshell.h

 
 #include "vimwrapper.h"
 
-typedef enum { CLEARALL, FILLRECT, DRAWSTRING, DRAWRECT, INVERTRECT, SCROLLRECT, DRAWSIGN} PaintOperationType;
-class PaintOperation {
-public:
-	PaintOperationType type;
-	QRect rect;
-	QColor color;
-	// DRAWSTRING
-	QFont font;
-	QString str;
-	bool undercurl;
-	QColor curlcolor;
-	// SIGN
-	QPixmap sign;
-	// SCROLL
-	QPoint pos;
-};
 
-class QVimShell: public QWidget
+class QVimShell: public QWidget, public VimWrapper
 {
 	Q_OBJECT
+	Q_ENUMS(PaintOperationType)
 public:
+	enum PaintOperationType { CLEARALL=0, FILLRECT, DRAWSTRING, DRAWRECT, INVERTRECT, SCROLLRECT, DRAWSIGN};
+	class PaintOperation {
+	public:
+		enum QVimShell::PaintOperationType type;
+		QRect rect;
+		QColor color;
+		// DRAWSTRING
+		QFont font;
+		QString str;
+		bool undercurl;
+		QColor curlcolor;
+		// SIGN
+		QPixmap sign;
+		// SCROLL
+		QPoint pos;
+	};
+
 	QVimShell(QWidget *parent=0);
 
 	bool hasInput();
 	bool m_encoding_utf8;
 
 	QQueue<PaintOperation> paintOps;
-	QPixmap canvas;
 
 	QTime m_lastClick;
 	int m_lastClickEvent;
 	QLabel *m_tooltip;
 
-	VimWrapper vim;
 	bool m_slowStringDrawing;
 	bool m_mouseHidden;
 };

File src/qt/vimevents.cpp

+#include "vimevents.h"
+#include "vimwrapper.h"
+
+VimEvent::VimEvent(VimWrapper &vim)
+:vim(vim)
+{
+}
+
+ResizeEvent::ResizeEvent(VimWrapper &vim, int w, int h)
+:VimEvent(vim), width(w), height(h)
+{
+}
+
+void ResizeEvent::handle()
+{
+	vim.guiResizeShell(width, height);
+}
+
+CloseEvent::CloseEvent(VimWrapper& vim)
+:VimEvent(vim)
+{
+}
+
+void CloseEvent::handle()
+{
+	vim.guiShellClosed();
+}
+
+DropEvent::DropEvent(VimWrapper& vim, const QPoint& pos, unsigned int mod, QList<QUrl> urls)
+:VimEvent(vim), pos(pos), mod(mod), urls(urls)
+{
+}
+
+void DropEvent::handle()
+{
+	vim.guiHandleDrop(pos, mod, urls);
+}
+

File src/qt/vimevents.h

+#ifndef VIM_QT_VIMEVENT
+#define VIM_QT_VIMEVENT
+
+#include <QPoint>
+#include <QList>
+#include <QUrl>
+
+struct VimWrapper;
+// Base class
+class VimEvent {
+public:
+	VimEvent(VimWrapper& vim);
+	virtual void handle()=0;
+protected:
+	VimWrapper& vim;
+};
+
+
+class ResizeEvent: public VimEvent
+{
+public:
+	ResizeEvent(VimWrapper& vim, int w, int h);
+	void handle();
+private:
+	int width, height;
+
+};
+
+class CloseEvent: public VimEvent
+{
+public:
+	CloseEvent(VimWrapper& vim);
+	void handle();
+};
+
+class DropEvent: public VimEvent
+{
+public:
+	DropEvent(VimWrapper& vim, const QPoint& pos, unsigned int mod, QList<QUrl> urls);
+	void handle();
+private:
+	QPoint pos;
+	unsigned int mod;
+	QList<QUrl> urls;
+};
+
+#endif

File src/qt/vimwrapper.cpp

-#include "vimwrapper.moc"
 #include <QApplication>
 #include <QStyle>
 #include <QMetaType>
+#include <QTime>
+#include <QTimer>
+#include <QTimer>
+#include <QTime>
+#include "vimwrapper.h"
 
 extern "C" {
 #include "vim.h"
 
 Q_DECLARE_METATYPE( QList<QUrl> );
 
-VimWrapper::VimWrapper(QObject *parent)
-:QObject(parent)
+VimWrapper::VimWrapper()
+:m_processInputOnly(false)
 {
 	qRegisterMetaType<QList<QUrl> >("URLList");
 
 
 void VimWrapper::guiResizeShell(int w, int h)
 {
-	QMetaObject::invokeMethod(this, 
-				"slot_guiResizeShell", Qt::QueuedConnection, 
-				Q_ARG(int, w), 
-				Q_ARG(int, h)
-			);
-	
-}
-void VimWrapper::slot_guiResizeShell(int w, int h)
-{
-	gui_resize_shell(w,h);
+	if ( m_processInputOnly ) {
+		ResizeEvent *ev = new ResizeEvent( *this, w, h);
+		pendingEvents.append(ev);
+	} else {
+		gui_resize_shell(w, h);
+	}
 }
 
 void VimWrapper::guiShellClosed()
 {
-	QMetaObject::invokeMethod(this, 
-				"slot_guiShellClosed", 
-				Qt::QueuedConnection);
-}
-void VimWrapper::slot_guiShellClosed()
-{
-	gui_shell_closed();
+	if ( m_processInputOnly ) {
+		pendingEvents.append(new CloseEvent(*this));
+	} else {
+		gui_shell_closed();
+	}
 }
 
 void VimWrapper::guiSendMouseEvent(int button, int x, int y, int repeated_click, unsigned int modifiers)
 {
-	QMetaObject::invokeMethod(this, 
-				"slot_guiSendMouseEvent", Qt::QueuedConnection, 
-				Q_ARG(int, button), 
-				Q_ARG(int, x), 
-				Q_ARG(int, y), 
-				Q_ARG(int, repeated_click), 
-				Q_ARG(unsigned int, modifiers)
-				);
-}
-void VimWrapper::slot_guiSendMouseEvent(int button, int x, int y, int repeated_click, unsigned int modifiers)
-{
+	// This is safe
 	gui_send_mouse_event(button, x, y, repeated_click, modifiers);
 }
 
 void VimWrapper::guiMouseMoved(int x, int y)
 {
-	QMetaObject::invokeMethod(this, 
-				"slot_guiMouseMoved",  Qt::QueuedConnection, 
-				Q_ARG(int, x),
-				Q_ARG(int, y)
-				);
-
-}
-void VimWrapper::slot_guiMouseMoved(int x, int y)
-{
 	gui_mouse_moved(x, y);
 }
 
 void VimWrapper::guiFocusChanged(int focus)
 {
-	QMetaObject::invokeMethod(this, 
-				"slot_guiFocusChanged", 
-				Qt::QueuedConnection, Q_ARG(int, focus));
-}
-void VimWrapper::slot_guiFocusChanged(int focus)
-{
 	gui_focus_change(focus);
 }
 
 void VimWrapper::sendTablineEvent(int ev)
 {
+	// This just writes to the input buf
 	send_tabline_event(ev);
 }
 
 
 void VimWrapper::sendTablineMenuEvent(int idx, int ev)
 {
+	// This just writes to the input buf
 	send_tabline_menu_event(idx, ev);
 }
 
-void VimWrapper::guiHandleDrop(int x, int y, unsigned int mod, const QList<QUrl> urls)
+/**
+ * Place text into the '~' register and push
+ * drop event into the input buffer
+ */
+void VimWrapper::guiHandleDropText(const QString& s)
 {
-	QMetaObject::invokeMethod(this, 
-				"slot_guiHandleDrop", 
-				Qt::QueuedConnection, 
-				Q_ARG(int, x),
-				Q_ARG(int, y),
-				Q_ARG(unsigned int, mod),
-				Q_ARG(QList<QUrl>, urls)
-				);
+	QByteArray text = convertTo(s);
+	dnd_yank_drag_data( (char_u*)text.data(), text.size());
+
+	char_u buf[3] = {CSI, KS_EXTRA, (char_u)KE_DROP};
+	add_to_input_buf(buf, 3);
 }
-void VimWrapper::slot_guiHandleDrop(int x, int y, unsigned int mod, const QList<QUrl> urls)
+
+void VimWrapper::guiHandleDrop(const QPoint& pos, unsigned int mod, const QList<QUrl> urls)
 {
 	if ( urls.size() == 0 ) {
 		return;
 	}
 
-	char_u **fnames = (char_u**)alloc( urls.size() * sizeof(char_u*));
-	int i;
-	for (i=0; i<urls.size(); i++) {
-		QByteArray encoded;
-		if ( urls.at(i).scheme() == "file" ) {
-			encoded = convertTo(urls.at(i).toLocalFile());
-		} else {
-			encoded = convertTo(urls.at(i).toString());
-		}
-
-		char *s = (char*)alloc(encoded.size()*sizeof(char)+1);
-		int j;
-		for (j=0; j<encoded.size(); j++) {
-			s[j] = encoded.at(j);
+	if ( m_processInputOnly ) {
+		DropEvent *ev = new DropEvent( *this, pos, mod, urls);
+		pendingEvents.append(ev);
+	} else {
+	
+		char_u **fnames = (char_u**)alloc( urls.size() * sizeof(char_u*));
+		int i;
+		for (i=0; i<urls.size(); i++) {
+			QByteArray encoded;
+			if ( urls.at(i).scheme() == "file" ) {
+				encoded = convertTo(urls.at(i).toLocalFile());
+			} else {
+				encoded = convertTo(urls.at(i).toString());
+			}
+	
+			char *s = (char*)alloc(encoded.size()*sizeof(char)+1);
+			int j;
+			for (j=0; j<encoded.size(); j++) {
+				s[j] = encoded.at(j);
+			}
+			s[j]='\0';
+			fnames[i] = (char_u *) s;
 		}
-		s[j]='\0';
-		fnames[i] = (char_u *) s;
+		gui_handle_drop(pos.x(), pos.y(), mod, fnames, urls.size());
 	}
-	gui_handle_drop(x, y, 0, fnames, urls.size());
 }
 
 
 		p_fullscreen = FALSE;
 	}
 }
+
+/**
+ *
+ *  wtime == -1	    Wait forever.
+ *  wtime == 0	    Process what you have and exit
+ *  wtime > 0	    Wait wtime milliseconds for a character.
+ *
+ *  Just like gui_mch_wait_for_chars we return OK if there is
+ *  input or FAIL otherwise
+ */
+bool VimWrapper::processEvents(long wtime, bool inputOnly)
+{
+	bool prev = m_processInputOnly;
+	m_processInputOnly = inputOnly;
+
+	// Process pending events
+	if (!inputOnly) {
+		while(pendingEvents.size() > 0) {
+			VimEvent *ev = pendingEvents.takeFirst();
+			ev->handle();
+			delete ev;
+		}
+	}
+
+	int ret = FAIL;
+	if ( wtime == -1 ) {
+		QApplication::processEvents( QEventLoop::WaitForMoreEvents);
+	} else if ( wtime == 0 ) {
+		QApplication::processEvents();
+	} else {
+		QTime t;
+		t.start();
+		do {
+			QTimer::singleShot( wtime - t.elapsed(),
+						QApplication::instance(),
+						SLOT(quit())
+					);
+			QApplication::processEvents( QEventLoop::WaitForMoreEvents);
+			if ( hasPendingEvents() || !vim_is_input_buf_empty() ) {
+				goto out;
+			}
+		} while( t.elapsed() < wtime );
+	}
+
+out:
+	m_processInputOnly = prev;
+	if ( hasPendingEvents() || !vim_is_input_buf_empty() ) {
+		return OK;
+	} else {
+		return FAIL;
+	}
+}
+
+bool VimWrapper::hasPendingEvents()
+{
+	return pendingEvents.size() != 0;
+}
+

File src/qt/vimwrapper.h

 #include "vim.h"
 }
 
-class VimWrapper: public QObject
+#include "vimevents.h"
+
+/**
+ * VimWrapper is wrapper around Vim, it handles conversion between Qt types
+ * and vim function's argument types
+ *
+ */
+class VimWrapper
 {
-	Q_OBJECT
 public:
-	VimWrapper(QObject *parent=0);
+	VimWrapper();
 	
 	/**
 	 * Map a row/col coordinate to a point in widget coordinates
 	/**
 	 * Vim methods
 	 */
-	void guiResizeShell(int, int);
+	//void guiResizeShell(int, int);
+	void guiResizeShell(int w, int h);
 	void guiShellClosed();
-	void guiSendMouseEvent(int, int);
 	void guiSendMouseEvent(int , int , int , int , unsigned int );
 	void guiMouseMoved(int, int);
 	void guiFocusChanged(int);
-	void guiHandleDrop(int, int, unsigned int, const QList<QUrl>);
+
+	void guiHandleDropText(const QString&);
+	void guiHandleDrop(const QPoint& , unsigned int, const QList<QUrl>);
 
 	void sendTablineEvent(int);
 	void sendTablineMenuEvent(int, int);
 	void undrawCursor();
 
 	static void setFullscreen(bool on);
+	void setProcessInputOnly(bool input_only);
+	bool processEvents(long wtime=0, bool inputOnly=false);
 
 protected:
 	static QString convertFrom(const char *, int size=-1);
+	bool hasPendingEvents();
 
-private slots:
-
-	/**
-	 * Vim methods slots
-	 */
-	void slot_guiResizeShell(int, int);
-	void slot_guiShellClosed();
-	void slot_guiSendMouseEvent(int , int , int , int , unsigned int );
-	void slot_guiMouseMoved(int, int);
-	void slot_guiFocusChanged(int);
-	void slot_guiHandleDrop(int, int, unsigned int, const QList<QUrl>);
-
-//	void guiMenuCb(long);
-
+private:
+	bool m_processInputOnly;
+	QList<VimEvent *> pendingEvents;
 };
 
 #endif