krita

kis_canvas.h

00001 /*
00002  *  Copyright (c) 1999 Matthias Elter  <me@kde.org>
00003  *  Copyright (c) 2004-2006 Adrian Page <adrian@pagenet.plus.com>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #ifndef KIS_CANVAS_H_
00021 #define KIS_CANVAS_H_
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <qwidget.h>
00028 #ifdef HAVE_GL
00029 #include <qgl.h>
00030 #endif
00031 #include <qpainter.h>
00032 
00033 #include "kis_global.h"
00034 #include "kis_point.h"
00035 #include "kis_vec.h"
00036 #include "kis_input_device.h"
00037 
00038 #ifdef Q_WS_X11
00039 
00040 // Irix has a different (and better) XInput tablet driver to
00041 // the XFree/xorg driver. Qt needs a separate code path for that
00042 // and so would we.
00043 #if defined(HAVE_XINPUTEXT) && !defined(Q_OS_IRIX)
00044 #define EXTENDED_X11_TABLET_SUPPORT
00045 #endif
00046 
00047 #include <map>
00048 #include <X11/Xlib.h>
00049 
00050 #if defined(EXTENDED_X11_TABLET_SUPPORT)
00051 #include <X11/extensions/XInput.h>
00052 #endif
00053 
00054 #endif // Q_WS_X11
00055 
00056 class KisEvent;
00057 class KisMoveEvent;
00058 class KisButtonPressEvent;
00059 class KisButtonReleaseEvent;
00060 class KisDoubleClickEvent;
00061 class KisCanvasWidgetPainter;
00062 
00063 class KisCanvasWidget : public QObject {
00064     Q_OBJECT
00065 
00066 public:
00067     KisCanvasWidget();
00068     virtual ~KisCanvasWidget();
00069     
00070     // When enabled, the canvas may throw away move events if the application
00071     // is unable to keep up with them, i.e. intermediate move events in the event
00072     // queue are skipped.
00073     void enableMoveEventCompressionHint(bool enableMoveCompression) { m_enableMoveEventCompressionHint = enableMoveCompression; }
00074 
00075     virtual KisCanvasWidgetPainter *createPainter() = 0;
00076 
00077 #ifdef EXTENDED_X11_TABLET_SUPPORT
00078     static KisInputDevice findActiveInputDevice();
00079     virtual void selectTabletDeviceEvents() = 0;
00080 
00081     static void selectTabletDeviceEvents(QWidget *widget);
00082 #endif
00083 
00084 #ifdef Q_WS_X11
00085     static void initX11Support();
00086 #endif
00087 
00088 signals:
00089     void sigGotPaintEvent(QPaintEvent*);
00090     void sigGotEnterEvent(QEvent*);
00091     void sigGotLeaveEvent(QEvent*);
00092     void sigGotMouseWheelEvent(QWheelEvent*);
00093     void sigGotKeyPressEvent(QKeyEvent*);
00094     void sigGotKeyReleaseEvent(QKeyEvent*);
00095     void sigGotDragEnterEvent(QDragEnterEvent*);
00096     void sigGotDropEvent(QDropEvent*);
00097     void sigGotMoveEvent(KisMoveEvent *);
00098     void sigGotButtonPressEvent(KisButtonPressEvent *);
00099     void sigGotButtonReleaseEvent(KisButtonReleaseEvent *);
00100     void sigGotDoubleClickEvent(KisDoubleClickEvent *);
00101 
00102 protected:
00103     void widgetGotPaintEvent(QPaintEvent *event);
00104     void widgetGotMousePressEvent(QMouseEvent *event);
00105     void widgetGotMouseReleaseEvent(QMouseEvent *event);
00106     void widgetGotMouseDoubleClickEvent(QMouseEvent *event);
00107     void widgetGotMouseMoveEvent(QMouseEvent *event);
00108     void widgetGotTabletEvent(QTabletEvent *event);
00109     void widgetGotEnterEvent(QEvent *event );
00110     void widgetGotLeaveEvent(QEvent *event);
00111     void widgetGotWheelEvent(QWheelEvent *event);
00112     void widgetGotKeyPressEvent(QKeyEvent *event);
00113     void widgetGotKeyReleaseEvent(QKeyEvent *event);
00114     void widgetGotDragEnterEvent(QDragEnterEvent *event);
00115     void widgetGotDropEvent(QDropEvent *event);
00116     void moveEvent(KisMoveEvent *event);
00117     void buttonPressEvent(KisButtonPressEvent *event);
00118     void buttonReleaseEvent(KisButtonReleaseEvent *event);
00119     void doubleClickEvent(KisDoubleClickEvent *event);
00120     void translateTabletEvent(KisEvent *event);
00121 
00122 protected:
00123 
00124     bool m_enableMoveEventCompressionHint;
00125     double m_lastPressure;
00126 
00127 #ifdef Q_WS_X11
00128     // On X11 systems, Qt throws away mouse move events if the application
00129     // is unable to keep up with them. We override this behaviour so that
00130     // we receive all move events, so that painting follows the mouse's motion
00131     // accurately.
00132     bool x11Event(XEvent *event, Display *x11Display, WId winId, QPoint widgetOriginPos);
00133     static Qt::ButtonState translateX11ButtonState(int state);
00134     static Qt::ButtonState translateX11Button(unsigned int button);
00135 
00136     static bool X11SupportInitialised;
00137 
00138     // Modifier masks for alt/meta - detected at run-time
00139     static long X11AltMask;
00140     static long X11MetaMask;
00141 
00142     int m_lastRootX;
00143     int m_lastRootY;
00144 
00145 #ifdef EXTENDED_X11_TABLET_SUPPORT
00146 
00147 public:
00148     class X11TabletDevice
00149     {
00150     public:
00151         X11TabletDevice();
00152         X11TabletDevice(const XDeviceInfo *deviceInfo);
00153 
00154         bool mightBeTabletDevice() const { return m_mightBeTabletDevice; }
00155         bool needsFindingActiveByProximity() const;
00156 
00157         XID id() const { return m_deviceId; }
00158         XDevice *xDevice() const { return m_XDevice; }
00159         QString name() const { return m_name; }
00160 
00161         KisInputDevice inputDevice() const { return m_inputDevice; }
00162         void setInputDevice(KisInputDevice inputDevice) { m_inputDevice = inputDevice; }
00163 
00164         void setEnabled(bool enabled);
00165         bool enabled() const;
00166 
00167         Q_INT32 numAxes() const;
00168 
00169         void setXAxis(Q_INT32 axis);
00170         void setYAxis(Q_INT32 axis);
00171         void setPressureAxis(Q_INT32 axis);
00172         void setXTiltAxis(Q_INT32 axis);
00173         void setYTiltAxis(Q_INT32 axis);
00174         void setWheelAxis(Q_INT32 axis);
00175         void setToolIDAxis(Q_INT32 axis);
00176         void setSerialNumberAxis(Q_INT32 axis);
00177 
00178         static const Q_INT32 NoAxis = -1;
00179         static const Q_INT32 DefaultAxis = -2;
00180 
00181         Q_INT32 xAxis() const;
00182         Q_INT32 yAxis() const;
00183         Q_INT32 pressureAxis() const;
00184         Q_INT32 xTiltAxis() const;
00185         Q_INT32 yTiltAxis() const;
00186         Q_INT32 wheelAxis() const;
00187         Q_INT32 toolIDAxis() const;
00188         Q_INT32 serialNumberAxis() const;
00189 
00190         void readSettingsFromConfig();
00191         void writeSettingsToConfig();
00192 
00193         // These return -1 if the device does not support the event
00194         int buttonPressEvent() const { return m_buttonPressEvent; }
00195         int buttonReleaseEvent() const { return m_buttonReleaseEvent; }
00196         int motionNotifyEvent() const { return m_motionNotifyEvent; }
00197         int proximityInEvent() const { return m_proximityInEvent; }
00198         int proximityOutEvent() const { return m_proximityOutEvent; }
00199 
00200         void enableEvents(QWidget *widget) const;
00201 
00202         class State
00203         {
00204         public:
00205             State() {}
00206             State(const KisPoint& pos, double pressure, const KisVector2D& tilt, double wheel,
00207                   Q_UINT32 toolID, Q_UINT32 serialNumber);
00208 
00209             // Position, pressure and wheel are normalised to 0 - 1
00210             KisPoint pos() const { return m_pos; }
00211             double pressure() const { return m_pressure; }
00212             // Tilt is normalised to -1->+1
00213             KisVector2D tilt() const { return m_tilt; }
00214             double wheel() const { return m_wheel; }
00215             // Wacom tool id and serial number of device.
00216             Q_UINT32 toolID() const { return m_toolID; }
00217             Q_UINT32 serialNumber() const { return m_serialNumber; }
00218 
00219         private:
00220             KisPoint m_pos;
00221             double m_pressure;
00222             KisVector2D m_tilt;
00223             double m_wheel;
00224             Q_UINT32 m_toolID;
00225             Q_UINT32 m_serialNumber;
00226         };
00227 
00228         State translateAxisData(const int *axisData) const;
00229 
00230     private:
00231         double translateAxisValue(int value, const XAxisInfo& axisInfo) const;
00232 
00233         XID m_deviceId;
00234         XDevice *m_XDevice;
00235 
00236         QString m_name;
00237 
00238         bool m_mightBeTabletDevice;
00239         KisInputDevice m_inputDevice;
00240 
00241         bool m_enabled;
00242 
00243         Q_INT32 m_xAxis;
00244         Q_INT32 m_yAxis;
00245         Q_INT32 m_pressureAxis;
00246         Q_INT32 m_xTiltAxis;
00247         Q_INT32 m_yTiltAxis;
00248         Q_INT32 m_wheelAxis;
00249         Q_INT32 m_toolIDAxis;
00250         Q_INT32 m_serialNumberAxis;
00251 
00252         QValueVector<XAxisInfo> m_axisInfo;
00253 
00254         int m_motionNotifyEvent;
00255         int m_buttonPressEvent;
00256         int m_buttonReleaseEvent;
00257         int m_proximityInEvent;
00258         int m_proximityOutEvent;
00259 
00260         QValueVector<XEventClass> m_eventClassList;
00261     };
00262 
00263     typedef std::map<XID, X11TabletDevice> X11XIDTabletDeviceMap;
00264     static X11XIDTabletDeviceMap& tabletDeviceMap();
00265 
00266 protected:
00267     static int X11DeviceMotionNotifyEvent;
00268     static int X11DeviceButtonPressEvent;
00269     static int X11DeviceButtonReleaseEvent;
00270     static int X11ProximityInEvent;
00271     static int X11ProximityOutEvent;
00272 
00273     static X11XIDTabletDeviceMap X11TabletDeviceMap;
00274 
00275 #endif // EXTENDED_X11_TABLET_SUPPORT
00276 
00277 #endif // Q_WS_X11
00278 };
00279 
00280 class KisCanvas : public QObject {
00281     Q_OBJECT
00282 
00283 public:
00284     KisCanvas(QWidget *parent, const char *name);
00285     virtual ~KisCanvas();
00286     
00287     // When enabled, the canvas may throw away move events if the application
00288     // is unable to keep up with them, i.e. intermediate move events in the event
00289     // queue are skipped.
00290     void enableMoveEventCompressionHint(bool enableMoveCompression);
00291 
00292     bool isOpenGLCanvas() const;
00293 
00297     bool cursorIsOverCanvas() const;
00298 
00303     void handleKeyEvent(QEvent *e);
00304 
00305     int width() const;
00306     int height() const;
00307 
00308     void update();
00309     void update(const QRect& r);
00310     void update(int x, int y, int width, int height);
00311     void repaint();
00312     void repaint(bool erase);
00313     void repaint(int x, int y, int width, int height, bool erase = true);
00314     void repaint(const QRect& r, bool erase = true);
00315     void repaint(const QRegion& r, bool erase = true);
00316 
00317     void updateGeometry();
00318 
00319 #if defined(EXTENDED_X11_TABLET_SUPPORT)
00320     void selectTabletDeviceEvents();
00321 #endif
00322 
00323 signals:
00324     void sigGotPaintEvent(QPaintEvent*);
00325     void sigGotEnterEvent(QEvent*);
00326     void sigGotLeaveEvent(QEvent*);
00327     void sigGotMouseWheelEvent(QWheelEvent*);
00328     void sigGotKeyPressEvent(QKeyEvent*);
00329     void sigGotKeyReleaseEvent(QKeyEvent*);
00330     void sigGotDragEnterEvent(QDragEnterEvent*);
00331     void sigGotDropEvent(QDropEvent*);
00332     void sigGotMoveEvent(KisMoveEvent *);
00333     void sigGotButtonPressEvent(KisButtonPressEvent *);
00334     void sigGotButtonReleaseEvent(KisButtonReleaseEvent *);
00335     void sigGotDoubleClickEvent(KisDoubleClickEvent *);
00336 
00337 protected:
00338     // Allow KisView to render on the widget directly, but everything else
00339     // has restricted access.
00340     friend class KisView;
00341     friend class KisCanvasPainter;
00342 
00343     // One of these will be valid, the other null. In Qt3, using a QPainter on
00344     // a QGLWidget is not reliable.
00345     QWidget *QPaintDeviceWidget() const;
00346 #ifdef HAVE_GL
00347     QGLWidget *OpenGLWidget() const;
00348 #endif
00349     void createQPaintDeviceCanvas();
00350 #ifdef HAVE_GL
00351     void createOpenGLCanvas(QGLWidget *sharedContextWidget);
00352 #endif
00353     void show();
00354     void hide();
00355     void setGeometry(int x, int y, int width, int height);
00356 
00357     void setUpdatesEnabled(bool updatesEnabled);
00358     bool isUpdatesEnabled() const;
00359 
00360     void setFocusPolicy(QWidget::FocusPolicy focusPolicy);
00361 
00362     const QCursor& cursor() const;
00363     void setCursor(const QCursor& cursor);
00364 
00365     KisCanvasWidgetPainter *createPainter();
00366     KisCanvasWidget *canvasWidget() const;
00367 
00368 protected:
00369 #ifdef HAVE_GL
00370     void createCanvasWidget(bool useOpenGL, QGLWidget *sharedContextWidget = 0);
00371 #else
00372     void createCanvasWidget(bool useOpenGL);
00373 #endif
00374     QWidget *m_parent;
00375     QString m_name;
00376     KisCanvasWidget *m_canvasWidget;
00377     bool m_enableMoveEventCompressionHint;
00378     bool m_useOpenGL;
00379 };
00380 
00381 #endif // KIS_CANVAS_H_
00382 
KDE Home | KDE Accessibility Home | Description of Access Keys