krita

kis_canvas.cc

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.g
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  Some of the X11-specific event handling code is based upon code from
00021  src/kernel/qapplication_x11.cpp from the Qt GUI Toolkit and is subject
00022  to the following license and copyright:
00023 
00024  ****************************************************************************
00025 **
00026 **
00027 ** Implementation of X11 startup routines and event handling
00028 **
00029 ** Created : 931029
00030 **
00031 ** Copyright (C) 1992-2003 Trolltech AS.  All rights reserved.
00032 **
00033 ** This file is part of the kernel module of the Qt GUI Toolkit.
00034 **
00035 ** This file may be distributed under the terms of the Q Public License
00036 ** as defined by Trolltech AS of Norway and appearing in the file
00037 ** LICENSE.QPL included in the packaging of this file.
00038 **
00039 ** This file may be distributed and/or modified under the terms of the
00040 ** GNU General Public License version 2 as published by the Free Software
00041 ** Foundation and appearing in the file LICENSE.GPL included in the
00042 ** packaging of this file.
00043 **
00044 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00045 ** licenses for Unix/X11 may use this file in accordance with the Qt Commercial
00046 ** License Agreement provided with the Software.
00047 **
00048 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00049 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00050 **
00051 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00052 **   information about Qt Commercial License Agreements.
00053 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00054 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00055 **
00056 ** Contact info@trolltech.com if any conditions of this licensing are
00057 ** not clear to you.
00058 **
00059 **********************************************************************/
00060 
00061 #include <qcursor.h>
00062 
00063 #include "kis_canvas.h"
00064 #include "kis_cursor.h"
00065 #include "kis_move_event.h"
00066 #include "kis_button_press_event.h"
00067 #include "kis_button_release_event.h"
00068 #include "kis_double_click_event.h"
00069 #include "kis_config.h"
00070 #include "kis_qpaintdevice_canvas.h"
00071 #include "kis_opengl_canvas.h"
00072 #include "kis_config.h"
00073 #include "kis_input_device.h"
00074 #include "fixx11h.h"
00075 
00076 #ifdef Q_WS_X11
00077 
00078 #include <qdesktopwidget.h>
00079 #include <qapplication.h>
00080 
00081 #include <X11/keysym.h>
00082 
00083 bool KisCanvasWidget::X11SupportInitialised = false;
00084 long KisCanvasWidget::X11AltMask = 0;
00085 long KisCanvasWidget::X11MetaMask = 0;
00086 
00087 #if defined(EXTENDED_X11_TABLET_SUPPORT)
00088 
00089 int KisCanvasWidget::X11DeviceMotionNotifyEvent = -1;
00090 int KisCanvasWidget::X11DeviceButtonPressEvent = -1;
00091 int KisCanvasWidget::X11DeviceButtonReleaseEvent = -1;
00092 int KisCanvasWidget::X11ProximityInEvent = -1;
00093 int KisCanvasWidget::X11ProximityOutEvent = -1;
00094 
00095 //X11XIDTabletDeviceMap KisCanvasWidget::X11TabletDeviceMap;
00096 std::map<XID, KisCanvasWidget::X11TabletDevice> KisCanvasWidget::X11TabletDeviceMap;
00097 
00098 #endif // EXTENDED_X11_TABLET_SUPPORT
00099 
00100 #endif // Q_WS_X11
00101 
00102 KisCanvasWidget::KisCanvasWidget()
00103 {
00104     m_enableMoveEventCompressionHint = false;
00105     m_lastPressure = 0;
00106 
00107 #ifdef Q_WS_X11
00108     if (!X11SupportInitialised) {
00109         initX11Support();
00110     }
00111 
00112     m_lastRootX = -1;
00113     m_lastRootY = -1;
00114 #endif
00115 }
00116 
00117 KisCanvasWidget::~KisCanvasWidget()
00118 {
00119 }
00120 
00121 void KisCanvasWidget::widgetGotPaintEvent(QPaintEvent *e)
00122 {
00123     emit sigGotPaintEvent(e);
00124 }
00125 
00126 void KisCanvasWidget::widgetGotMousePressEvent(QMouseEvent *e)
00127 {
00128     KisButtonPressEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->button(), e->state());
00129     buttonPressEvent(&ke);
00130 }
00131 
00132 void KisCanvasWidget::widgetGotMouseReleaseEvent(QMouseEvent *e)
00133 {
00134     KisButtonReleaseEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->button(), e->state());
00135     buttonReleaseEvent(&ke);
00136 }
00137 
00138 void KisCanvasWidget::widgetGotMouseDoubleClickEvent(QMouseEvent *e)
00139 {
00140     KisDoubleClickEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->button(), e->state());
00141     doubleClickEvent(&ke);
00142 }
00143 
00144 void KisCanvasWidget::widgetGotMouseMoveEvent(QMouseEvent *e)
00145 {
00146     KisMoveEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->state());
00147     moveEvent(&ke);
00148 }
00149 
00150 void KisCanvasWidget::widgetGotTabletEvent(QTabletEvent *e)
00151 {
00152     KisInputDevice device;
00153 
00154     switch (e->device()) {
00155     default:
00156     case QTabletEvent::NoDevice:
00157     case QTabletEvent::Stylus:
00158         device = KisInputDevice::stylus();
00159         break;
00160     case QTabletEvent::Puck:
00161         device = KisInputDevice::puck();
00162         break;
00163     case QTabletEvent::Eraser:
00164         device = KisInputDevice::eraser();
00165         break;
00166     }
00167 
00168     double pressure = e->pressure() / 255.0;
00169 
00170     if (e->type() == QEvent::TabletPress) {
00171         KisButtonPressEvent ke(device, e->pos(), e->globalPos(), pressure, e->xTilt(), e->yTilt(), Qt::LeftButton, Qt::NoButton);
00172         translateTabletEvent(&ke);
00173     }
00174     else
00175     if (e->type() == QEvent::TabletRelease) {
00176         KisButtonReleaseEvent ke(device, e->pos(), e->globalPos(), pressure, e->xTilt(), e->yTilt(), Qt::LeftButton, Qt::NoButton);
00177         translateTabletEvent(&ke);
00178     }
00179     else {
00180         KisMoveEvent ke(device, e->pos(), e->globalPos(), pressure, e->xTilt(), e->yTilt(), Qt::NoButton);
00181         translateTabletEvent(&ke);
00182 #ifdef Q_WS_X11
00183         // Fix the problem that when you change from using a tablet device to the mouse,
00184         // the first mouse button event is not recognised. This is because we handle
00185         // X11 core mouse move events directly so Qt does not get to see them. This breaks
00186         // the tablet event accept/ignore mechanism, causing Qt to consume the first
00187         // mouse button event it sees, instead of a mouse move. 'Ignoring' tablet move events
00188         // stops Qt from stealing the next mouse button event. This does not affect the
00189         // tablet aware tools as they do not care about mouse moves while the tablet device is
00190         // drawing.
00191         e->ignore();
00192 #endif
00193     }
00194 }
00195 
00196 void KisCanvasWidget::widgetGotEnterEvent(QEvent *e)
00197 {
00198     emit sigGotEnterEvent(e);
00199 }
00200 
00201 void KisCanvasWidget::widgetGotLeaveEvent(QEvent *e)
00202 {
00203     emit sigGotLeaveEvent(e);
00204 }
00205 
00206 void KisCanvasWidget::widgetGotWheelEvent(QWheelEvent *e)
00207 {
00208     emit sigGotMouseWheelEvent(e);
00209 }
00210 
00211 void KisCanvasWidget::widgetGotKeyPressEvent(QKeyEvent *e)
00212 {
00213     emit sigGotKeyPressEvent(e);
00214 }
00215 
00216 void KisCanvasWidget::widgetGotKeyReleaseEvent(QKeyEvent *e)
00217 {
00218     emit sigGotKeyReleaseEvent(e);
00219 }
00220 
00221 void KisCanvasWidget::widgetGotDragEnterEvent(QDragEnterEvent *e)
00222 {
00223     emit sigGotDragEnterEvent(e);
00224 }
00225 
00226 void KisCanvasWidget::widgetGotDropEvent(QDropEvent *e)
00227 {
00228     emit sigGotDropEvent(e);
00229 }
00230 
00231 void KisCanvasWidget::moveEvent(KisMoveEvent *e)
00232 {
00233     emit sigGotMoveEvent(e);
00234 }
00235 
00236 void KisCanvasWidget::buttonPressEvent(KisButtonPressEvent *e)
00237 {
00238     QWidget *widget = dynamic_cast<QWidget *>(this);
00239     Q_ASSERT(widget != 0);
00240 
00241     if (widget) {
00242         widget->setFocus();
00243     }
00244 
00245     emit sigGotButtonPressEvent(e);
00246 }
00247 
00248 void KisCanvasWidget::buttonReleaseEvent(KisButtonReleaseEvent *e)
00249 {
00250     emit sigGotButtonReleaseEvent(e);
00251 }
00252 
00253 void KisCanvasWidget::doubleClickEvent(KisDoubleClickEvent *e)
00254 {
00255     emit sigGotDoubleClickEvent(e);
00256 }
00257 
00258 void KisCanvasWidget::translateTabletEvent(KisEvent *e)
00259 {
00260     bool checkThresholdOnly = false;
00261 
00262     if (e->type() == KisEvent::ButtonPressEvent || e->type() == KisEvent::ButtonReleaseEvent) {
00263         KisButtonEvent *b = static_cast<KisButtonEvent *>(e);
00264 
00265         if (b->button() == Qt::MidButton || b->button() == Qt::RightButton) {
00266 
00267             if (e->type() == KisEvent::ButtonPressEvent) {
00268                 buttonPressEvent(static_cast<KisButtonPressEvent *>(e));
00269             } else {
00270                 buttonReleaseEvent(static_cast<KisButtonReleaseEvent *>(e));
00271             }
00272 
00273             checkThresholdOnly = true;
00274         }
00275     }
00276 
00277     // Use pressure threshold to detect 'left button' press/release
00278     if (e->pressure() >= PRESSURE_THRESHOLD && m_lastPressure < PRESSURE_THRESHOLD) {
00279         KisButtonPressEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), Qt::LeftButton, e->state());
00280         buttonPressEvent(&ke);
00281     } else if (e->pressure() < PRESSURE_THRESHOLD && m_lastPressure >= PRESSURE_THRESHOLD) {
00282         KisButtonReleaseEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), Qt::LeftButton, e->state());
00283         buttonReleaseEvent(&ke);
00284     } else {
00285         if (!checkThresholdOnly) {
00286             KisMoveEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->state());
00287             moveEvent(&ke);
00288         }
00289     }
00290 
00291     m_lastPressure = e->pressure();
00292 }
00293 
00294 #ifdef Q_WS_X11
00295 
00296 void KisCanvasWidget::initX11Support()
00297 {
00298     if (X11SupportInitialised)
00299     {
00300         return;
00301     }
00302 
00303     X11SupportInitialised = true;
00304 
00305     Display *x11Display = QApplication::desktop()->x11Display();
00306 
00307     // Look at the modifier mapping and get the correct masks for alt/meta
00308     XModifierKeymap *map = XGetModifierMapping(x11Display);
00309 
00310     if (map) {
00311         int mapIndex = 0;
00312 
00313         for (int maskIndex = 0; maskIndex < 8; maskIndex++) {
00314             for (int i = 0; i < map->max_keypermod; i++) {
00315                 if (map->modifiermap[mapIndex]) {
00316 
00317                     KeySym sym = XKeycodeToKeysym(x11Display, map->modifiermap[mapIndex], 0);
00318 
00319                     if (X11AltMask == 0 && (sym == XK_Alt_L || sym == XK_Alt_R)) {
00320                         X11AltMask = 1 << maskIndex;
00321                     }
00322                     if (X11MetaMask == 0 && (sym == XK_Meta_L || sym == XK_Meta_R)) {
00323                         X11MetaMask = 1 << maskIndex;
00324                     }
00325                 }
00326 
00327                 mapIndex++;
00328             }
00329         }
00330 
00331         XFreeModifiermap(map);
00332     }
00333     else {
00334         // Assume defaults
00335         X11AltMask = Mod1Mask;
00336         X11MetaMask = Mod4Mask;
00337     }
00338 
00339 #if defined(EXTENDED_X11_TABLET_SUPPORT)
00340 
00341     int numDevices = 0;
00342     const XDeviceInfo *devices = XListInputDevices(x11Display, &numDevices);
00343 
00344     if (devices != NULL) {
00345         XID lastStylusSeen = 0;
00346         XID lastEraserSeen = 0;
00347         bool foundStylus = false;
00348         bool foundEraser = false;
00349 
00350         for (int i = 0; i < numDevices; i++) {
00351 
00352             const XDeviceInfo *device = devices + i;
00353             X11TabletDevice tabletDevice(device);
00354 
00355             if (tabletDevice.mightBeTabletDevice()) {
00356 
00357                 tabletDevice.readSettingsFromConfig();
00358 
00359                 QString lowerCaseName = tabletDevice.name().lower();
00360 
00361                 // Find the devices that Qt will use as its stylus and eraser devices.
00362                 if (!foundStylus || !foundEraser) {
00363                     if (lowerCaseName.startsWith("stylus") || lowerCaseName.startsWith("pen")) {
00364                         lastStylusSeen = device->id;
00365                         foundStylus = true;
00366                     }
00367                     else if (lowerCaseName.startsWith("eraser")) {
00368                         lastEraserSeen = device->id;
00369                         foundEraser = true;
00370                     }
00371                 }
00372 
00373                 X11TabletDeviceMap[device->id] = tabletDevice;
00374 
00375                 // Event types are device-independent. Store any
00376                 // the device supports.
00377                 if (tabletDevice.buttonPressEvent() >= 0) {
00378                     X11DeviceButtonPressEvent = tabletDevice.buttonPressEvent();
00379                 }
00380                 if (tabletDevice.buttonReleaseEvent() >= 0) {
00381                     X11DeviceButtonReleaseEvent = tabletDevice.buttonReleaseEvent();
00382                 }
00383                 if (tabletDevice.motionNotifyEvent() >= 0) {
00384                     X11DeviceMotionNotifyEvent = tabletDevice.motionNotifyEvent();
00385                 }
00386                 if (tabletDevice.proximityInEvent() >= 0) {
00387                     X11ProximityInEvent = tabletDevice.proximityInEvent();
00388                 }
00389                 if (tabletDevice.proximityOutEvent() >= 0) {
00390                     X11ProximityOutEvent = tabletDevice.proximityOutEvent();
00391                 }
00392             }
00393         }
00394 
00395         // Allocate input devices.
00396         for (X11XIDTabletDeviceMap::iterator it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) {
00397 
00398             X11TabletDevice& tabletDevice = (*it).second;
00399 
00400             if (foundStylus && tabletDevice.id() == lastStylusSeen) {
00401                 tabletDevice.setInputDevice(KisInputDevice::stylus());
00402             } else if (foundEraser && tabletDevice.id() == lastEraserSeen) {
00403                 tabletDevice.setInputDevice(KisInputDevice::eraser());
00404             } else {
00405                 tabletDevice.setInputDevice(KisInputDevice::allocateInputDevice());
00406             }
00407         }
00408 
00409         XFreeDeviceList(const_cast<XDeviceInfo *>(devices));
00410     }
00411 #endif // EXTENDED_X11_TABLET_SUPPORT
00412 }
00413 
00414 Qt::ButtonState KisCanvasWidget::translateX11ButtonState(int state)
00415 {
00416     int buttonState = 0;
00417 
00418     if (state & Button1Mask)
00419         buttonState |= Qt::LeftButton;
00420     if (state & Button2Mask)
00421         buttonState |= Qt::MidButton;
00422     if (state & Button3Mask)
00423         buttonState |= Qt::RightButton;
00424     if (state & ShiftMask)
00425         buttonState |= Qt::ShiftButton;
00426     if (state & ControlMask)
00427         buttonState |= Qt::ControlButton;
00428     if (state & X11AltMask)
00429         buttonState |= Qt::AltButton;
00430     if (state & X11MetaMask)
00431         buttonState |= Qt::MetaButton;
00432 
00433     return static_cast<Qt::ButtonState>(buttonState);
00434 }
00435 
00436 Qt::ButtonState KisCanvasWidget::translateX11Button(unsigned int X11Button)
00437 {
00438     Qt::ButtonState qtButton;
00439 
00440     switch (X11Button) {
00441     case Button1:
00442         qtButton = Qt::LeftButton;
00443         break;
00444     case Button2:
00445         qtButton = Qt::MidButton;
00446         break;
00447     case Button3:
00448         qtButton = Qt::RightButton;
00449         break;
00450     default:
00451         qtButton = Qt::NoButton;
00452     }
00453 
00454     return qtButton;
00455 }
00456 
00457 #if defined(EXTENDED_X11_TABLET_SUPPORT)
00458 
00459 KisCanvasWidget::X11TabletDevice::X11TabletDevice()
00460 {
00461     m_mightBeTabletDevice = false;
00462     m_inputDevice = KisInputDevice::unknown();
00463     m_enabled = false;
00464     m_xAxis = NoAxis;
00465     m_yAxis = NoAxis;
00466     m_pressureAxis = NoAxis;
00467     m_xTiltAxis = NoAxis;
00468     m_yTiltAxis = NoAxis;
00469     m_wheelAxis = NoAxis;
00470     m_toolIDAxis = NoAxis;
00471     m_serialNumberAxis = NoAxis;
00472     m_buttonPressEvent = -1;
00473     m_buttonReleaseEvent = -1;
00474     m_motionNotifyEvent = -1;
00475     m_proximityInEvent = -1;
00476     m_proximityOutEvent = -1;
00477 }
00478 
00479 KisCanvasWidget::X11TabletDevice::X11TabletDevice(const XDeviceInfo *deviceInfo)
00480 {
00481     m_mightBeTabletDevice = false;
00482     m_inputDevice = KisInputDevice::unknown();
00483     m_enabled = false;
00484     m_xAxis = NoAxis;
00485     m_yAxis = NoAxis;
00486     m_pressureAxis = NoAxis;
00487     m_xTiltAxis = NoAxis;
00488     m_yTiltAxis = NoAxis;
00489     m_wheelAxis = NoAxis;
00490     m_toolIDAxis = NoAxis;
00491     m_serialNumberAxis = NoAxis;
00492 
00493     m_deviceId = deviceInfo->id;
00494     m_name = deviceInfo->name;
00495 
00496     // Get the ranges of the valuators
00497     XAnyClassPtr classInfo = const_cast<XAnyClassPtr>(deviceInfo->inputclassinfo);
00498 
00499     for (int i = 0; i < deviceInfo->num_classes; i++) {
00500 
00501         if (classInfo->c_class == ValuatorClass) {
00502 
00503             const XValuatorInfo *valuatorInfo = reinterpret_cast<const XValuatorInfo *>(classInfo);
00504 
00505             // Need at least x, y, and pressure.
00506 
00507             if (valuatorInfo->num_axes >= 3) {
00508 
00509                 for (unsigned int axis = 0; axis < valuatorInfo->num_axes; axis++) {
00510                     m_axisInfo.append(valuatorInfo->axes[axis]);
00511                 }
00512 
00513                 m_mightBeTabletDevice = true;
00514             }
00515         }
00516 
00517         classInfo = reinterpret_cast<XAnyClassPtr>(reinterpret_cast<char *>(classInfo) + classInfo->length);
00518     }
00519 
00520     // Determine the event types it supports. We're only interested in
00521     // buttons and motion at the moment.
00522     m_buttonPressEvent = -1;
00523     m_buttonReleaseEvent = -1;
00524     m_motionNotifyEvent = -1;
00525     m_proximityInEvent = -1;
00526     m_proximityOutEvent = -1;
00527 
00528     m_XDevice = XOpenDevice(QApplication::desktop()->x11Display(), m_deviceId);
00529 
00530     if (m_XDevice != NULL) {
00531         for (int i = 0; i < m_XDevice->num_classes; i++) {
00532 
00533             XEventClass eventClass;
00534 
00535             if (m_XDevice->classes[i].input_class == ButtonClass) {
00536                 DeviceButtonPress(m_XDevice, m_buttonPressEvent, eventClass);
00537                 m_eventClassList.append(eventClass);
00538 
00539                 DeviceButtonRelease(m_XDevice, m_buttonReleaseEvent, eventClass);
00540                 m_eventClassList.append(eventClass);
00541             }
00542             else
00543             if (m_XDevice->classes[i].input_class == ValuatorClass) {
00544                 DeviceMotionNotify(m_XDevice, m_motionNotifyEvent, eventClass);
00545                 m_eventClassList.append(eventClass);
00546             }
00547             else
00548             if (m_XDevice->classes[i].input_class == ProximityClass) {
00549                 ProximityIn(m_XDevice, m_proximityInEvent, eventClass);
00550                 m_eventClassList.append(eventClass);
00551 
00552                 ProximityOut(m_XDevice, m_proximityOutEvent, eventClass);
00553                 m_eventClassList.append(eventClass);
00554             }
00555         }
00556 
00557         // Note: We don't XCloseXDevice() since Qt will have already opened
00558         // it, and only one XCloseDevice() call closes it for all opens.
00559     }
00560 
00561     if (m_buttonPressEvent == -1 || m_buttonReleaseEvent == -1 || m_motionNotifyEvent == -1) {
00562         m_mightBeTabletDevice = false;
00563     }
00564 }
00565 
00566 void KisCanvasWidget::X11TabletDevice::setEnabled(bool enabled)
00567 {
00568     m_enabled = enabled;
00569 }
00570 
00571 bool KisCanvasWidget::X11TabletDevice::enabled() const
00572 {
00573     return m_enabled;
00574 }
00575 
00576 Q_INT32 KisCanvasWidget::X11TabletDevice::numAxes() const
00577 {
00578     return m_axisInfo.count();
00579 }
00580 
00581 void KisCanvasWidget::X11TabletDevice::setXAxis(Q_INT32 axis)
00582 {
00583     m_xAxis = axis;
00584 }
00585 
00586 void KisCanvasWidget::X11TabletDevice::setYAxis(Q_INT32 axis)
00587 {
00588     m_yAxis = axis;
00589 }
00590 
00591 void KisCanvasWidget::X11TabletDevice::setPressureAxis(Q_INT32 axis)
00592 {
00593     m_pressureAxis = axis;
00594 }
00595 
00596 void KisCanvasWidget::X11TabletDevice::setXTiltAxis(Q_INT32 axis)
00597 {
00598     m_xTiltAxis = axis;
00599 }
00600 
00601 void KisCanvasWidget::X11TabletDevice::setYTiltAxis(Q_INT32 axis)
00602 {
00603     m_yTiltAxis = axis;
00604 }
00605 
00606 void KisCanvasWidget::X11TabletDevice::setWheelAxis(Q_INT32 axis)
00607 {
00608     m_wheelAxis = axis;
00609 }
00610 
00611 void KisCanvasWidget::X11TabletDevice::setToolIDAxis(Q_INT32 axis)
00612 {
00613     m_toolIDAxis = axis;
00614 }
00615 
00616 void KisCanvasWidget::X11TabletDevice::setSerialNumberAxis(Q_INT32 axis)
00617 {
00618     m_serialNumberAxis = axis;
00619 }
00620 
00621 Q_INT32 KisCanvasWidget::X11TabletDevice::xAxis() const
00622 {
00623     return m_xAxis;
00624 }
00625 
00626 Q_INT32 KisCanvasWidget::X11TabletDevice::yAxis() const
00627 {
00628     return m_yAxis;
00629 }
00630 
00631 Q_INT32 KisCanvasWidget::X11TabletDevice::pressureAxis() const
00632 {
00633     return m_pressureAxis;
00634 }
00635 
00636 Q_INT32 KisCanvasWidget::X11TabletDevice::xTiltAxis() const
00637 {
00638     return m_xTiltAxis;
00639 }
00640 
00641 Q_INT32 KisCanvasWidget::X11TabletDevice::yTiltAxis() const
00642 {
00643     return m_yTiltAxis;
00644 }
00645 
00646 Q_INT32 KisCanvasWidget::X11TabletDevice::wheelAxis() const
00647 {
00648     return m_wheelAxis;
00649 }
00650 
00651 Q_INT32 KisCanvasWidget::X11TabletDevice::toolIDAxis() const
00652 {
00653     return m_toolIDAxis;
00654 }
00655 
00656 Q_INT32 KisCanvasWidget::X11TabletDevice::serialNumberAxis() const
00657 {
00658     return m_serialNumberAxis;
00659 }
00660 
00661 void KisCanvasWidget::X11TabletDevice::readSettingsFromConfig()
00662 {
00663     KisConfig cfg;
00664 
00665     m_enabled = cfg.tabletDeviceEnabled(m_name);
00666 
00667     m_xAxis = cfg.tabletDeviceAxis(m_name, "XAxis", DefaultAxis);
00668     m_yAxis = cfg.tabletDeviceAxis(m_name, "YAxis", DefaultAxis);
00669     m_pressureAxis = cfg.tabletDeviceAxis(m_name, "PressureAxis", DefaultAxis);
00670     m_xTiltAxis = cfg.tabletDeviceAxis(m_name, "XTiltAxis", DefaultAxis);
00671     m_yTiltAxis = cfg.tabletDeviceAxis(m_name, "YTiltAxis", DefaultAxis);
00672     m_wheelAxis = cfg.tabletDeviceAxis(m_name, "WheelAxis", DefaultAxis);
00673     m_toolIDAxis = cfg.tabletDeviceAxis(m_name, "ToolIDAxis", DefaultAxis);
00674     m_serialNumberAxis = cfg.tabletDeviceAxis(m_name, "SerialNumberAxis", DefaultAxis);
00675 
00676     if (!m_enabled && m_xAxis == DefaultAxis && m_yAxis == DefaultAxis && m_pressureAxis == DefaultAxis &&
00677          m_xTiltAxis == DefaultAxis && m_yTiltAxis == DefaultAxis && m_wheelAxis == DefaultAxis &&
00678          m_toolIDAxis == DefaultAxis && m_serialNumberAxis == DefaultAxis) {
00679         // This is the first time this device has been seen. Set up default values, assuming
00680         // it's a Wacom pad.
00681         m_xAxis = 0;
00682         m_yAxis = 1;
00683         m_pressureAxis = 2;
00684 
00685         if (m_axisInfo.count() >= 4) {
00686             m_xTiltAxis = 3;
00687         } else {
00688             m_xTiltAxis = NoAxis;
00689         }
00690 
00691         if (m_axisInfo.count() >= 5) {
00692             m_yTiltAxis = 4;
00693         } else {
00694             m_yTiltAxis = NoAxis;
00695         }
00696 
00697         if (m_axisInfo.count() >= 6) {
00698             m_wheelAxis = 5;
00699         } else {
00700             m_wheelAxis = NoAxis;
00701         }
00702 
00703         // Available since driver version 0.7.2.
00704         if (m_axisInfo.count() >= 7) {
00705             m_toolIDAxis = 6;
00706         } else {
00707             m_toolIDAxis = NoAxis;
00708         }
00709 
00710         if (m_axisInfo.count() >= 8) {
00711             m_serialNumberAxis = 7;
00712         } else {
00713             m_serialNumberAxis = NoAxis;
00714         }
00715     }
00716 }
00717 
00718 void KisCanvasWidget::X11TabletDevice::writeSettingsToConfig()
00719 {
00720     KisConfig cfg;
00721 
00722     cfg.setTabletDeviceEnabled(m_name, m_enabled);
00723 
00724     cfg.setTabletDeviceAxis(m_name, "XAxis", m_xAxis);
00725     cfg.setTabletDeviceAxis(m_name, "YAxis", m_yAxis);
00726     cfg.setTabletDeviceAxis(m_name, "PressureAxis", m_pressureAxis);
00727     cfg.setTabletDeviceAxis(m_name, "XTiltAxis", m_xTiltAxis);
00728     cfg.setTabletDeviceAxis(m_name, "YTiltAxis", m_yTiltAxis);
00729     cfg.setTabletDeviceAxis(m_name, "WheelAxis", m_wheelAxis);
00730     cfg.setTabletDeviceAxis(m_name, "ToolIDAxis", m_toolIDAxis);
00731     cfg.setTabletDeviceAxis(m_name, "SerialNumberAxis", m_serialNumberAxis);
00732 }
00733 
00734 void KisCanvasWidget::X11TabletDevice::enableEvents(QWidget *widget) const
00735 {
00736     if (!m_eventClassList.isEmpty()) {
00737         int result = XSelectExtensionEvent(widget->x11AppDisplay(), widget->handle(), 
00738                                            const_cast<XEventClass*>(&m_eventClassList[0]), 
00739                                            m_eventClassList.count());
00740     
00741         if (result != Success) {
00742             kdDebug(41001) << "Failed to select extension events for " << m_name << endl;
00743         }
00744     }
00745 }
00746 
00747 double KisCanvasWidget::X11TabletDevice::translateAxisValue(int value, const XAxisInfo& axisInfo) const
00748 {
00749     int axisRange = axisInfo.max_value - axisInfo.min_value;
00750     double translatedValue = 0;
00751 
00752     if (axisRange != 0) {
00753         translatedValue = (static_cast<double>(value) - axisInfo.min_value) / axisRange;
00754         if (axisInfo.min_value < 0) {
00755             translatedValue -= 0.5;
00756         }
00757     }
00758 
00759     return translatedValue;
00760 }
00761 
00762 KisCanvasWidget::X11TabletDevice::State::State(const KisPoint& pos, double pressure, const KisVector2D& tilt, double wheel,
00763                                                Q_UINT32 toolID, Q_UINT32 serialNumber)
00764     : m_pos(pos), 
00765       m_pressure(pressure), 
00766       m_tilt(tilt),
00767       m_wheel(wheel),
00768       m_toolID(toolID),
00769       m_serialNumber(serialNumber)
00770 {
00771 }
00772 
00773 KisCanvasWidget::X11TabletDevice::State KisCanvasWidget::X11TabletDevice::translateAxisData(const int *axisData) const
00774 {
00775     KisPoint pos(0, 0);
00776 
00777     if (m_xAxis != NoAxis && m_yAxis != NoAxis) {
00778         pos = KisPoint(translateAxisValue(axisData[m_xAxis], m_axisInfo[m_xAxis]), 
00779                        translateAxisValue(axisData[m_yAxis], m_axisInfo[m_yAxis]));
00780     }
00781 
00782     double pressure = PRESSURE_DEFAULT;
00783 
00784     if (m_pressureAxis != NoAxis) {
00785         pressure = translateAxisValue(axisData[m_pressureAxis], m_axisInfo[m_pressureAxis]);
00786     }
00787 
00788     KisVector2D tilt = KisVector2D(0, 0);
00789     Q_UINT32 toolID = 0;
00790     Q_UINT32 serialNumber = 0;
00791 
00792     if (m_xTiltAxis != NoAxis) {
00793         // Latest wacom driver returns the tool id and serial number in 
00794         // the upper 16 bits of the x and y tilts and wheel.
00795         int xTiltAxisValue = (Q_INT16)(axisData[m_xTiltAxis] & 0xffff);
00796         toolID = ((Q_UINT32)axisData[m_xTiltAxis] >> 16) & 0xffff;
00797 
00798         tilt.setX(translateAxisValue(xTiltAxisValue, m_axisInfo[m_xTiltAxis]));
00799     }
00800 
00801     if (m_yTiltAxis != NoAxis) {
00802         int yTiltAxisValue = (Q_INT16)(axisData[m_yTiltAxis] & 0xffff);
00803         serialNumber = (Q_UINT32)axisData[m_yTiltAxis] & 0xffff0000;
00804 
00805         tilt.setY(translateAxisValue(yTiltAxisValue, m_axisInfo[m_yTiltAxis]));
00806     }
00807 
00808     double wheel = 0;
00809 
00810     if (m_wheelAxis != NoAxis) {
00811         int wheelAxisValue = (Q_INT16)(axisData[m_wheelAxis] & 0xffff);
00812         serialNumber |= ((Q_UINT32)axisData[m_wheelAxis] >> 16) & 0xffff;
00813 
00814         wheel = translateAxisValue(wheelAxisValue, m_axisInfo[m_wheelAxis]);
00815     }
00816 
00817     //QString ids;
00818     //ids.sprintf("Tool ID: %8x Serial Number: %8x", toolID, serialNumber);
00819 
00820     return State(pos, pressure, tilt, wheel, toolID, serialNumber);
00821 }
00822 
00823 KisCanvasWidget::X11XIDTabletDeviceMap& KisCanvasWidget::tabletDeviceMap()
00824 {
00825     return X11TabletDeviceMap;
00826 }
00827 
00828 void KisCanvasWidget::selectTabletDeviceEvents(QWidget *widget)
00829 {
00830     for (X11XIDTabletDeviceMap::const_iterator it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) {
00831 
00832         const X11TabletDevice& device = (*it).second;
00833 
00834         if (device.enabled()) {
00835             device.enableEvents(widget);
00836         }
00837     }
00838 }
00839 
00840 #endif // EXTENDED_X11_TABLET_SUPPORT
00841 
00842 bool KisCanvasWidget::x11Event(XEvent *event, Display *x11Display, WId winId, QPoint widgetOriginPos)
00843 {
00844     if (event->type == MotionNotify) {
00845         // Mouse move
00846         if (!m_enableMoveEventCompressionHint) {
00847 
00848             XMotionEvent motion = event->xmotion;
00849             QPoint globalPos(motion.x_root, motion.y_root);
00850 
00851             if (globalPos.x() != m_lastRootX || globalPos.y() != m_lastRootY) {
00852 
00853                 int state = translateX11ButtonState(motion.state);
00854                 QPoint pos(motion.x, motion.y);
00855                 QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, state);
00856 
00857                 widgetGotMouseMoveEvent(&e);
00858             }
00859 
00860             m_lastRootX = globalPos.x();
00861             m_lastRootY = globalPos.y();
00862 
00863             return true;
00864         }
00865         else {
00866             return false;
00867         }
00868     }
00869     else
00870 #if defined(EXTENDED_X11_TABLET_SUPPORT)
00871     if (event->type == X11DeviceMotionNotifyEvent || event->type == X11DeviceButtonPressEvent || event->type == X11DeviceButtonReleaseEvent) {
00872         // Tablet event.
00873         int deviceId;
00874         const int *axisData;
00875         Qt::ButtonState button;
00876         Qt::ButtonState buttonState;
00877 
00878         if (event->type == X11DeviceMotionNotifyEvent) {
00879             // Tablet move
00880             const XDeviceMotionEvent *motion = reinterpret_cast<const XDeviceMotionEvent *>(event);
00881             XEvent mouseEvent;
00882 
00883             // Look for an accompanying core event.
00884             if (XCheckTypedWindowEvent(x11Display, winId, MotionNotify, &mouseEvent)) {
00885                 if (motion->time == mouseEvent.xmotion.time) {
00886                     // Do nothing
00887                 } else {
00888                     XPutBackEvent(x11Display, &mouseEvent);
00889                 }
00890             }
00891 
00892             if (m_enableMoveEventCompressionHint) {
00893                 while (true) {
00894                     // Look for another motion notify in the queue and skip
00895                     // to that if found.
00896                     if (!XCheckTypedWindowEvent(x11Display, winId, X11DeviceMotionNotifyEvent, &mouseEvent)) {
00897                         break;
00898                     }
00899 
00900                     motion = reinterpret_cast<const XDeviceMotionEvent *>(&mouseEvent);
00901 
00902                     XEvent coreMotionEvent;
00903 
00904                     // Look for an accompanying core event.
00905                     if (!XCheckTypedWindowEvent(x11Display, winId, MotionNotify, &coreMotionEvent)) {
00906                         // Do nothing
00907                     }
00908                 }
00909             }
00910 
00911             deviceId = motion->deviceid;
00912             axisData = motion->axis_data;
00913             button = Qt::NoButton;
00914             buttonState = translateX11ButtonState(motion->state);
00915         }
00916         else
00917         if (event->type == X11DeviceButtonPressEvent) {
00918             // Tablet button press
00919             const XDeviceButtonPressedEvent *buttonPressed = reinterpret_cast<const XDeviceButtonPressedEvent *>(event);
00920             deviceId = buttonPressed->deviceid;
00921             axisData = buttonPressed->axis_data;
00922             button = translateX11Button(buttonPressed->button);
00923             buttonState = translateX11ButtonState(buttonPressed->state);
00924 
00925             if (QApplication::activePopupWidget() == 0) {
00926                 XEvent mouseEvent;
00927 
00928                 // Look for and swallow an accompanying core event, but only if there's
00929                 // no active popup, as that needs to see it.
00930                 if (XCheckTypedWindowEvent(x11Display, winId, ButtonPress, &mouseEvent)) {
00931                     if (buttonPressed->time == mouseEvent.xbutton.time) {
00932                         // Do nothing
00933                     }
00934                     else {
00935                         XPutBackEvent(x11Display, &mouseEvent);
00936                     }
00937                 }
00938             }
00939         }
00940         else {
00941             // Tablet button release
00942             const XDeviceButtonReleasedEvent *buttonReleased = reinterpret_cast<const XDeviceButtonReleasedEvent *>(event);
00943             deviceId = buttonReleased->deviceid;
00944             axisData = buttonReleased->axis_data;
00945             button = translateX11Button(buttonReleased->button);
00946             buttonState = translateX11ButtonState(buttonReleased->state);
00947 
00948             if (QApplication::activePopupWidget() == 0) {
00949                 XEvent mouseEvent;
00950 
00951                 // Look for and swallow an accompanying core event, but only if there's
00952                 // no active popup, as that needs to see it.
00953                 if (XCheckTypedWindowEvent(x11Display, winId, ButtonRelease, &mouseEvent)) {
00954                     if (buttonReleased->time == mouseEvent.xbutton.time) {
00955                         // Do nothing
00956                     }
00957                     else {
00958                         XPutBackEvent(x11Display, &mouseEvent);
00959                     }
00960                 }
00961             }
00962         }
00963 
00964         X11XIDTabletDeviceMap::const_iterator it = X11TabletDeviceMap.find(deviceId);
00965 
00966         if (it != X11TabletDeviceMap.end()) {
00967 
00968             const X11TabletDevice& tabletDevice = (*it).second;
00969 
00970             if (tabletDevice.enabled()) {
00971                 X11TabletDevice::State deviceState = tabletDevice.translateAxisData(axisData);
00972 
00973                 // Map normalised position coordinates to screen coordinates
00974                 QDesktopWidget *desktop = QApplication::desktop();
00975                 KisPoint globalPos(deviceState.pos().x() * desktop->width(), deviceState.pos().y() * desktop->height());
00976                 // Convert screen coordinates to widget coordinates
00977                 KisPoint pos = globalPos - KoPoint( widgetOriginPos );
00978 
00979                 // Map tilt to -60 - +60 degrees
00980                 KisVector2D tilt(deviceState.tilt().x() * 60, deviceState.tilt().y() * 60);
00981 
00982                 if (event->type == X11DeviceMotionNotifyEvent) {
00983                     KisMoveEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), buttonState);
00984                     translateTabletEvent(&e);
00985                 }
00986                 else
00987                 if (event->type == X11DeviceButtonPressEvent) {
00988                     KisButtonPressEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), button, buttonState);
00989                     translateTabletEvent(&e);
00990                 }
00991                 else {
00992                     KisButtonReleaseEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), button, buttonState);
00993                     translateTabletEvent(&e);
00994                 }
00995             }
00996 
00997             // Consume the event even if the device is disabled otherwise Qt will
00998             // process it and send a QTabletEvent.
00999             return true;
01000         }
01001         else {
01002             return false;
01003         }
01004     }
01005     else
01006 #endif // EXTENDED_X11_TABLET_SUPPORT
01007     {
01008         return false;
01009     }
01010 }
01011 
01012 #if defined(EXTENDED_X11_TABLET_SUPPORT)
01013 
01014 KisInputDevice KisCanvasWidget::findActiveInputDevice()
01015 {
01016     X11XIDTabletDeviceMap::const_iterator it;
01017 
01018     for (it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) {
01019         const X11TabletDevice& tabletDevice = (*it).second;
01020 
01021         XDeviceState *deviceState = XQueryDeviceState(QApplication::desktop()->x11Display(),
01022                                                       tabletDevice.xDevice());
01023 
01024         // If your the laptop sleeps, and you remove the mouse from the usb
01025         // port, then on wake-up Krita can crash because the above call will
01026         // return 0. 
01027         if (!deviceState) continue;
01028         
01029         const XInputClass *inputClass = deviceState->data;
01030         bool deviceIsInProximity = false;
01031 
01032         for (int i = 0; i < deviceState->num_classes; i++) {
01033 
01034             if (inputClass->c_class == ValuatorClass) {
01035 
01036                 const XValuatorState *valuatorState = reinterpret_cast<const XValuatorState *>(inputClass);
01037 
01038                 if ((valuatorState->mode & ProximityState) == InProximity) {
01039                     deviceIsInProximity = true;
01040                     break;
01041                 }
01042             }
01043 
01044             inputClass = reinterpret_cast<const XInputClass *>(reinterpret_cast<const char *>(inputClass) + inputClass->length);
01045         }
01046 
01047         XFreeDeviceState(deviceState);
01048 
01049         if (deviceIsInProximity && tabletDevice.enabled()) {
01050             return tabletDevice.inputDevice();
01051         }
01052     }
01053 
01054     return KisInputDevice::mouse();
01055 }
01056 
01057 #endif // EXTENDED_X11_TABLET_SUPPORT
01058 
01059 
01060 #endif // Q_WS_X11
01061 
01062 /*************************************************************************/
01063 
01064 #define QPAINTDEVICE_CANVAS_WIDGET false
01065 #define OPENGL_CANVAS_WIDGET true
01066 
01067 KisCanvas::KisCanvas(QWidget *parent, const char *name)
01068 {
01069     m_parent = parent;
01070     m_name = name;
01071     m_enableMoveEventCompressionHint = false;
01072     m_canvasWidget = 0;
01073     m_useOpenGL = false;
01074     createCanvasWidget(QPAINTDEVICE_CANVAS_WIDGET);
01075 }
01076 
01077 KisCanvas::~KisCanvas()
01078 {
01079     delete m_canvasWidget;
01080 }
01081 
01082 #ifdef HAVE_GL
01083 void KisCanvas::createCanvasWidget(bool useOpenGL, QGLWidget *sharedContextWidget)
01084 #else
01085 void KisCanvas::createCanvasWidget(bool useOpenGL)
01086 #endif
01087 {
01088     delete m_canvasWidget;
01089 
01090 #ifndef HAVE_GL
01091     useOpenGL = false;
01092 #else
01093     if (useOpenGL && !QGLFormat::hasOpenGL()) {
01094         kdDebug(41001) << "Tried to create OpenGL widget when system doesn't have OpenGL\n";
01095         useOpenGL = false;
01096     }
01097 
01098     if (useOpenGL) {
01099         m_canvasWidget = new KisOpenGLCanvasWidget(m_parent, m_name.latin1(), sharedContextWidget);
01100     } else
01101 #endif
01102     {
01103         m_canvasWidget = new KisQPaintDeviceCanvasWidget(m_parent, m_name.latin1());
01104     }
01105 
01106     m_useOpenGL = useOpenGL;
01107 
01108     Q_CHECK_PTR(m_canvasWidget);
01109     QWidget *widget = dynamic_cast<QWidget *>(m_canvasWidget);
01110 
01111     widget->setBackgroundMode(QWidget::NoBackground);
01112     widget->setMouseTracking(true);
01113     widget->setAcceptDrops(true);
01114     m_canvasWidget->enableMoveEventCompressionHint(m_enableMoveEventCompressionHint);
01115 
01116 #if defined(EXTENDED_X11_TABLET_SUPPORT)
01117     selectTabletDeviceEvents();
01118 #endif
01119 
01120     connect(m_canvasWidget, SIGNAL(sigGotPaintEvent(QPaintEvent *)), SIGNAL(sigGotPaintEvent(QPaintEvent *)));
01121     connect(m_canvasWidget, SIGNAL(sigGotEnterEvent(QEvent*)), SIGNAL(sigGotEnterEvent(QEvent*)));
01122     connect(m_canvasWidget, SIGNAL(sigGotLeaveEvent(QEvent*)), SIGNAL(sigGotLeaveEvent(QEvent*)));
01123     connect(m_canvasWidget, SIGNAL(sigGotMouseWheelEvent(QWheelEvent*)), SIGNAL(sigGotMouseWheelEvent(QWheelEvent*)));
01124     connect(m_canvasWidget, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), SIGNAL(sigGotKeyPressEvent(QKeyEvent*)));
01125     connect(m_canvasWidget, SIGNAL(sigGotKeyReleaseEvent(QKeyEvent*)), SIGNAL(sigGotKeyReleaseEvent(QKeyEvent*)));
01126     connect(m_canvasWidget, SIGNAL(sigGotDragEnterEvent(QDragEnterEvent*)), SIGNAL(sigGotDragEnterEvent(QDragEnterEvent*)));
01127     connect(m_canvasWidget, SIGNAL(sigGotDropEvent(QDropEvent*)), SIGNAL(sigGotDropEvent(QDropEvent*)));
01128     connect(m_canvasWidget, SIGNAL(sigGotMoveEvent(KisMoveEvent *)), SIGNAL(sigGotMoveEvent(KisMoveEvent *)));
01129     connect(m_canvasWidget, SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent *)), SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent *)));
01130     connect(m_canvasWidget, SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent *)), SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent *)));
01131     connect(m_canvasWidget, SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent *)), SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent *)));
01132 }
01133 
01134 void KisCanvas::createQPaintDeviceCanvas()
01135 {
01136     createCanvasWidget(QPAINTDEVICE_CANVAS_WIDGET);
01137 }
01138 
01139 #ifdef HAVE_GL
01140 void KisCanvas::createOpenGLCanvas(QGLWidget *sharedContextWidget)
01141 {
01142     createCanvasWidget(OPENGL_CANVAS_WIDGET, sharedContextWidget);
01143 }
01144 #endif
01145 
01146 bool KisCanvas::isOpenGLCanvas() const
01147 {
01148     return m_useOpenGL;
01149 }
01150 
01151 void KisCanvas::enableMoveEventCompressionHint(bool enableMoveCompression)
01152 {
01153     m_enableMoveEventCompressionHint = enableMoveCompression;
01154     if (m_canvasWidget != 0) {
01155         m_canvasWidget->enableMoveEventCompressionHint(enableMoveCompression);
01156     }
01157 }
01158 
01159 QWidget *KisCanvas::QPaintDeviceWidget() const
01160 {
01161     if (m_useOpenGL) {
01162         return 0;
01163     } else {
01164         return dynamic_cast<QWidget *>(m_canvasWidget);
01165     }
01166 }
01167 
01168 #ifdef HAVE_GL
01169 QGLWidget *KisCanvas::OpenGLWidget() const
01170 {
01171     if (m_useOpenGL) {
01172         return dynamic_cast<QGLWidget *>(m_canvasWidget);
01173     } else {
01174         return 0;
01175     }
01176 }
01177 #endif
01178 
01179 KisCanvasWidgetPainter *KisCanvas::createPainter()
01180 {
01181     Q_ASSERT(m_canvasWidget != 0);
01182     return m_canvasWidget->createPainter();
01183 }
01184 
01185 KisCanvasWidget *KisCanvas::canvasWidget() const
01186 {
01187     return m_canvasWidget;
01188 }
01189 
01190 void KisCanvas::setGeometry(int x, int y, int width, int height)
01191 {
01192     Q_ASSERT(m_canvasWidget);
01193     dynamic_cast<QWidget *>(m_canvasWidget)->setGeometry(x, y, width, height);
01194 }
01195 
01196 void KisCanvas::show()
01197 {
01198     Q_ASSERT(m_canvasWidget);
01199     dynamic_cast<QWidget *>(m_canvasWidget)->show();
01200 }
01201 
01202 void KisCanvas::hide()
01203 {
01204     Q_ASSERT(m_canvasWidget);
01205     dynamic_cast<QWidget *>(m_canvasWidget)->hide();
01206 }
01207 
01208 int KisCanvas::width() const
01209 {
01210     Q_ASSERT(m_canvasWidget);
01211     return dynamic_cast<QWidget *>(m_canvasWidget)->width();
01212 }
01213 
01214 int KisCanvas::height() const
01215 {
01216     Q_ASSERT(m_canvasWidget);
01217     return dynamic_cast<QWidget *>(m_canvasWidget)->height();
01218 }
01219 
01220 void KisCanvas::update()
01221 {
01222     Q_ASSERT(m_canvasWidget);
01223     dynamic_cast<QWidget *>(m_canvasWidget)->update();
01224 }
01225 
01226 void KisCanvas::update(const QRect& r)
01227 {
01228     Q_ASSERT(m_canvasWidget);
01229     dynamic_cast<QWidget *>(m_canvasWidget)->update(r);
01230 }
01231 
01232 void KisCanvas::update(int x, int y, int width, int height)
01233 {
01234     Q_ASSERT(m_canvasWidget);
01235     dynamic_cast<QWidget *>(m_canvasWidget)->update(x, y, width, height);
01236 }
01237 
01238 void KisCanvas::repaint()
01239 {
01240     Q_ASSERT(m_canvasWidget);
01241     dynamic_cast<QWidget *>(m_canvasWidget)->repaint();
01242 }
01243 
01244 void KisCanvas::repaint(bool erase)
01245 {
01246     Q_ASSERT(m_canvasWidget);
01247     dynamic_cast<QWidget *>(m_canvasWidget)->repaint(erase);
01248 }
01249 
01250 void KisCanvas::repaint(int x, int y, int width, int height, bool erase)
01251 {
01252     Q_ASSERT(m_canvasWidget);
01253     dynamic_cast<QWidget *>(m_canvasWidget)->repaint(x, y, width, height, erase);
01254 }
01255 
01256 void KisCanvas::repaint(const QRect& r, bool erase)
01257 {
01258     Q_ASSERT(m_canvasWidget);
01259     dynamic_cast<QWidget *>(m_canvasWidget)->repaint(r, erase);
01260 }
01261 
01262 void KisCanvas::repaint(const QRegion& r, bool erase)
01263 {
01264     Q_ASSERT(m_canvasWidget);
01265     dynamic_cast<QWidget *>(m_canvasWidget)->repaint(r, erase);
01266 }
01267 
01268 bool KisCanvas::isUpdatesEnabled() const
01269 {
01270     Q_ASSERT(m_canvasWidget);
01271     return dynamic_cast<QWidget *>(m_canvasWidget)->isUpdatesEnabled();
01272 }
01273 
01274 void KisCanvas::setUpdatesEnabled(bool updatesEnabled)
01275 {
01276     Q_ASSERT(m_canvasWidget);
01277     dynamic_cast<QWidget *>(m_canvasWidget)->setUpdatesEnabled(updatesEnabled);
01278 }
01279 
01280 void KisCanvas::updateGeometry()
01281 {
01282     Q_ASSERT(m_canvasWidget);
01283     dynamic_cast<QWidget *>(m_canvasWidget)->updateGeometry();
01284 }
01285 
01286 void KisCanvas::setFocusPolicy(QWidget::FocusPolicy focusPolicy)
01287 {
01288     Q_ASSERT(m_canvasWidget);
01289     dynamic_cast<QWidget *>(m_canvasWidget)->setFocusPolicy(focusPolicy);
01290 }
01291 
01292 const QCursor& KisCanvas::cursor() const
01293 {
01294     Q_ASSERT(m_canvasWidget);
01295     return dynamic_cast<QWidget *>(m_canvasWidget)->cursor();
01296 }
01297 
01298 void KisCanvas::setCursor(const QCursor& cursor)
01299 {
01300     Q_ASSERT(m_canvasWidget);
01301     dynamic_cast<QWidget *>(m_canvasWidget)->setCursor(cursor);
01302 }
01303 
01304 #if defined(EXTENDED_X11_TABLET_SUPPORT)
01305 void KisCanvas::selectTabletDeviceEvents()
01306 {
01307     Q_ASSERT(m_canvasWidget);
01308     m_canvasWidget->selectTabletDeviceEvents();
01309 }
01310 #endif
01311 
01312 bool KisCanvas::cursorIsOverCanvas() const
01313 {
01314     if (QApplication::activePopupWidget() != 0) {
01315         return false;
01316     }
01317     if (QApplication::activeModalWidget() != 0) {
01318         return false;
01319     }
01320 
01321     QWidget *canvasWidget = dynamic_cast<QWidget *>(m_canvasWidget);
01322     Q_ASSERT(canvasWidget != 0);
01323 
01324     if (canvasWidget) {
01325         if (QApplication::widgetAt(QCursor::pos(), true) == canvasWidget) {
01326             return true;
01327         }
01328     }
01329     return false;
01330 }
01331 
01332 void KisCanvas::handleKeyEvent(QEvent *e)
01333 {
01334     QKeyEvent *ke = dynamic_cast<QKeyEvent *>(e);
01335 
01336     Q_ASSERT(ke != 0);
01337 
01338     if (ke) {
01339         QWidget *canvasWidget = dynamic_cast<QWidget *>(m_canvasWidget);
01340         Q_ASSERT(canvasWidget != 0);
01341 
01342         if (canvasWidget) {
01343             canvasWidget->setFocus();
01344 
01345             if (e->type() == QEvent::KeyPress) {
01346                 emit sigGotKeyPressEvent(ke);
01347             } else {
01348                 emit sigGotKeyReleaseEvent(ke);
01349             }
01350         }
01351     }
01352 }
01353 
01354 #include "kis_canvas.moc"
01355 
KDE Home | KDE Accessibility Home | Description of Access Keys