I've written my own QGIS map tool class to access the protected member functions (canvasPressEvent, canvasReleaseEvent, etc) as well as to be able to limit the distance panned. Specifically I've subclassed this with the QgsMapToolPan class. It's pretty straight forward (this is C++, but the PyQGIS will look similar):
pan.h:
#ifndef PAN_H
#define PAN_H
#include <qgsmapcanvas.h>
#include <qgsmapmouseevent.h>
#include <qgsmaptoolpan.h>
#include <QObject>
class Pan : public QgsMapToolPan
{
Q_OBJECT
public:
Pan(QgsMapCanvas *qmc);
~Pan();
protected:
void canvasPressEvent(QgsMapMouseEvent *e);
void canvasReleaseEvent(QgsMapMouseEvent *e);
};
#endif // PAN_H
pan.cpp:
#include "include/pan.h"
Pan::Pan(QgsMapCanvas *qmc) : QgsMapToolPan(qmc)
{
activate();
setCursor(Qt::OpenHandCursor);
}
void Pan::canvasPressEvent(QgsMapMouseEvent *e)
{
setCursor(Qt::ClosedHandCursor);
}
void Pan::canvasReleaseEvent(QgsMapMouseEvent *e)
{
setCursor(Qt::OpenHandCursor);
}
Pan::~Pan()
{
deactivate();
}
However when the tool is activated and the user starts panning, it reverts back to the previous canvas extent and any change in zoom scale level keeps that extent constant. Here's an example of what I mean using OpenStreetMaps:
OpenStreetMap upon app launch
App after panning right. A subsequent pan action reverts back to image 1 first
Any subsequent zooming causes the white space to move in line with the cut off, hinting at a frozen canvas extent
I don't see anywhere in my code where I would be setting the map canvas' extent as its previous one so this action is puzzling. I've added canvas refresh commands but the tiles are still cut off.