chalk

kis_canvas.cpp
1/*
2 * Copyright (c) 1999 Matthias Elter <me@kde.org>
3 * Copyright (c) 2004-2006 Adrian Page <adrian@pagenet.plus.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.g
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19
20 Some of the X11-specific event handling code is based upon code from
21 src/kernel/qapplication_x11.cpp from the TQt GUI Toolkit and is subject
22 to the following license and copyright:
23
24 ****************************************************************************
25**
26**
27** Implementation of X11 startup routines and event handling
28**
29** Created : 931029
30**
31** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
32**
33** This file is part of the kernel module of the TQt GUI Toolkit.
34**
35** This file may be distributed under the terms of the Q Public License
36** as defined by Trolltech AS of Norway and appearing in the file
37** LICENSE.TQPL included in the packaging of this file.
38**
39** This file may be distributed and/or modified under the terms of the
40** GNU General Public License version 2 as published by the Free Software
41** Foundation and appearing in the file LICENSE.GPL included in the
42** packaging of this file.
43**
44** Licensees holding valid TQt Enterprise Edition or TQt Professional Edition
45** licenses for Unix/X11 may use this file in accordance with the TQt Commercial
46** License Agreement provided with the Software.
47**
48** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
49** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50**
51** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
52** information about TQt Commercial License Agreements.
53** See http://www.trolltech.com/qpl/ for TQPL licensing information.
54** See http://www.trolltech.com/gpl/ for GPL licensing information.
55**
56** Contact info@trolltech.com if any conditions of this licensing are
57** not clear to you.
58**
59**********************************************************************/
60
61#include <tqcursor.h>
62
63#include "kis_canvas.h"
64#include "kis_cursor.h"
65#include "kis_move_event.h"
66#include "kis_button_press_event.h"
67#include "kis_button_release_event.h"
68#include "kis_double_click_event.h"
69#include "kis_config.h"
70#include "kis_qpaintdevice_canvas.h"
71#include "kis_opengl_canvas.h"
72#include "kis_config.h"
73#include "kis_input_device.h"
74#include "fixx11h.h"
75
76#ifdef TQ_WS_X11
77
78#include <tqdesktopwidget.h>
79#include <tqapplication.h>
80
81#include <X11/XKBlib.h>
82#include <X11/keysym.h>
83
84bool KisCanvasWidget::X11SupportInitialised = false;
85long KisCanvasWidget::X11AltMask = 0;
86long KisCanvasWidget::X11MetaMask = 0;
87
88#if defined(EXTENDED_X11_TABLET_SUPPORT)
89
90int KisCanvasWidget::X11DeviceMotionNotifyEvent = -1;
91int KisCanvasWidget::X11DeviceButtonPressEvent = -1;
92int KisCanvasWidget::X11DeviceButtonReleaseEvent = -1;
93int KisCanvasWidget::X11ProximityInEvent = -1;
94int KisCanvasWidget::X11ProximityOutEvent = -1;
95
96//X11XIDTabletDeviceMap KisCanvasWidget::X11TabletDeviceMap;
97std::map<XID, KisCanvasWidget::X11TabletDevice> KisCanvasWidget::X11TabletDeviceMap;
98
99#endif // EXTENDED_X11_TABLET_SUPPORT
100
101#endif // TQ_WS_X11
102
103KisCanvasWidget::KisCanvasWidget()
104{
105 m_enableMoveEventCompressionHint = false;
106 m_lastPressure = 0;
107
108#ifdef TQ_WS_X11
109 if (!X11SupportInitialised) {
110 initX11Support();
111 }
112
113 m_lastRootX = -1;
114 m_lastRootY = -1;
115#endif
116}
117
118KisCanvasWidget::~KisCanvasWidget()
119{
120}
121
122void KisCanvasWidget::widgetGotPaintEvent(TQPaintEvent *e)
123{
124 emit sigGotPaintEvent(e);
125}
126
127void KisCanvasWidget::widgetGotMousePressEvent(TQMouseEvent *e)
128{
129 KisButtonPressEvent ke(KisInputDevice::mouse(), KisPoint(e->pos()), KisPoint(e->globalPos()), PRESSURE_DEFAULT, 0, 0, e->button(), e->state());
130 buttonPressEvent(&ke);
131}
132
133void KisCanvasWidget::widgetGotMouseReleaseEvent(TQMouseEvent *e)
134{
135 KisButtonReleaseEvent ke(KisInputDevice::mouse(), KisPoint(e->pos()), KisPoint(e->globalPos()), PRESSURE_DEFAULT, 0, 0, e->button(), e->state());
136 buttonReleaseEvent(&ke);
137}
138
139void KisCanvasWidget::widgetGotMouseDoubleClickEvent(TQMouseEvent *e)
140{
141 KisDoubleClickEvent ke(KisInputDevice::mouse(), KisPoint(e->pos()), KisPoint(e->globalPos()), PRESSURE_DEFAULT, 0, 0, e->button(), e->state());
142 doubleClickEvent(&ke);
143}
144
145void KisCanvasWidget::widgetGotMouseMoveEvent(TQMouseEvent *e)
146{
147 KisMoveEvent ke(KisInputDevice::mouse(), KisPoint(e->pos()), KisPoint(e->globalPos()), PRESSURE_DEFAULT, 0, 0, e->state());
148 moveEvent(&ke);
149}
150
151void KisCanvasWidget::widgetGotTabletEvent(TQTabletEvent *e)
152{
153 KisInputDevice device;
154
155 switch (e->device()) {
156 default:
157 case TQTabletEvent::NoDevice:
158 case TQTabletEvent::Stylus:
159 device = KisInputDevice::stylus();
160 break;
161 case TQTabletEvent::Puck:
162 device = KisInputDevice::puck();
163 break;
164 case TQTabletEvent::Eraser:
165 device = KisInputDevice::eraser();
166 break;
167 }
168
169 double pressure = e->pressure() / 255.0;
170
171 if (e->type() == TQEvent::TabletPress) {
172 KisButtonPressEvent ke(device, KisPoint(e->pos()), KisPoint(e->globalPos()), pressure, e->xTilt(), e->yTilt(), TQt::LeftButton, TQt::NoButton);
173 translateTabletEvent(&ke);
174 }
175 else
176 if (e->type() == TQEvent::TabletRelease) {
177 KisButtonReleaseEvent ke(device, KisPoint(e->pos()), KisPoint(e->globalPos()), pressure, e->xTilt(), e->yTilt(), TQt::LeftButton, TQt::NoButton);
178 translateTabletEvent(&ke);
179 }
180 else {
181 KisMoveEvent ke(device, KisPoint(e->pos()), KisPoint(e->globalPos()), pressure, e->xTilt(), e->yTilt(), TQt::NoButton);
182 translateTabletEvent(&ke);
183#ifdef TQ_WS_X11
184 // Fix the problem that when you change from using a tablet device to the mouse,
185 // the first mouse button event is not recognised. This is because we handle
186 // X11 core mouse move events directly so TQt does not get to see them. This breaks
187 // the tablet event accept/ignore mechanism, causing TQt to consume the first
188 // mouse button event it sees, instead of a mouse move. 'Ignoring' tablet move events
189 // stops TQt from stealing the next mouse button event. This does not affect the
190 // tablet aware tools as they do not care about mouse moves while the tablet device is
191 // drawing.
192 e->ignore();
193#endif
194 }
195}
196
197void KisCanvasWidget::widgetGotEnterEvent(TQEvent *e)
198{
199 emit sigGotEnterEvent(e);
200}
201
202void KisCanvasWidget::widgetGotLeaveEvent(TQEvent *e)
203{
204 emit sigGotLeaveEvent(e);
205}
206
207void KisCanvasWidget::widgetGotWheelEvent(TQWheelEvent *e)
208{
209 emit sigGotMouseWheelEvent(e);
210}
211
212void KisCanvasWidget::widgetGotKeyPressEvent(TQKeyEvent *e)
213{
214 emit sigGotKeyPressEvent(e);
215}
216
217void KisCanvasWidget::widgetGotKeyReleaseEvent(TQKeyEvent *e)
218{
219 emit sigGotKeyReleaseEvent(e);
220}
221
222void KisCanvasWidget::widgetGotDragEnterEvent(TQDragEnterEvent *e)
223{
224 emit sigGotDragEnterEvent(e);
225}
226
227void KisCanvasWidget::widgetGotDropEvent(TQDropEvent *e)
228{
229 emit sigGotDropEvent(e);
230}
231
232void KisCanvasWidget::moveEvent(KisMoveEvent *e)
233{
234 emit sigGotMoveEvent(e);
235}
236
237void KisCanvasWidget::buttonPressEvent(KisButtonPressEvent *e)
238{
239 TQWidget *widget = dynamic_cast<TQWidget *>(this);
240 Q_ASSERT(widget != 0);
241
242 if (widget) {
243 widget->setFocus();
244 }
245
246 emit sigGotButtonPressEvent(e);
247}
248
249void KisCanvasWidget::buttonReleaseEvent(KisButtonReleaseEvent *e)
250{
251 emit sigGotButtonReleaseEvent(e);
252}
253
254void KisCanvasWidget::doubleClickEvent(KisDoubleClickEvent *e)
255{
256 emit sigGotDoubleClickEvent(e);
257}
258
259void KisCanvasWidget::translateTabletEvent(KisEvent *e)
260{
261 bool checkThresholdOnly = false;
262
263 if (e->type() == KisEvent::ButtonPressEvent || e->type() == KisEvent::ButtonReleaseEvent) {
264 KisButtonEvent *b = static_cast<KisButtonEvent *>(e);
265
266 if (b->button() == TQt::MidButton || b->button() == TQt::RightButton) {
267
268 if (e->type() == KisEvent::ButtonPressEvent) {
269 buttonPressEvent(static_cast<KisButtonPressEvent *>(e));
270 } else {
271 buttonReleaseEvent(static_cast<KisButtonReleaseEvent *>(e));
272 }
273
274 checkThresholdOnly = true;
275 }
276 }
277
278 // Use pressure threshold to detect 'left button' press/release
279 if (e->pressure() >= PRESSURE_THRESHOLD && m_lastPressure < PRESSURE_THRESHOLD) {
280 KisButtonPressEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), TQt::LeftButton, e->state());
281 buttonPressEvent(&ke);
282 } else if (e->pressure() < PRESSURE_THRESHOLD && m_lastPressure >= PRESSURE_THRESHOLD) {
283 KisButtonReleaseEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), TQt::LeftButton, e->state());
284 buttonReleaseEvent(&ke);
285 } else {
286 if (!checkThresholdOnly) {
287 KisMoveEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->state());
288 moveEvent(&ke);
289 }
290 }
291
292 m_lastPressure = e->pressure();
293}
294
295#ifdef TQ_WS_X11
296
297void KisCanvasWidget::initX11Support()
298{
299 if (X11SupportInitialised)
300 {
301 return;
302 }
303
304 X11SupportInitialised = true;
305
306 Display *x11Display = TQApplication::desktop()->x11Display();
307
308 // Look at the modifier mapping and get the correct masks for alt/meta
309 XModifierKeymap *map = XGetModifierMapping(x11Display);
310
311 if (map) {
312 int mapIndex = 0;
313
314 for (int maskIndex = 0; maskIndex < 8; maskIndex++) {
315 for (int i = 0; i < map->max_keypermod; i++) {
316 if (map->modifiermap[mapIndex]) {
317
318 KeySym sym = XkbKeycodeToKeysym(x11Display, map->modifiermap[mapIndex], 0, 0);
319
320 if (X11AltMask == 0 && (sym == XK_Alt_L || sym == XK_Alt_R)) {
321 X11AltMask = 1 << maskIndex;
322 }
323 if (X11MetaMask == 0 && (sym == XK_Meta_L || sym == XK_Meta_R)) {
324 X11MetaMask = 1 << maskIndex;
325 }
326 }
327
328 mapIndex++;
329 }
330 }
331
332 XFreeModifiermap(map);
333 }
334 else {
335 // Assume defaults
336 X11AltMask = Mod1Mask;
337 X11MetaMask = Mod4Mask;
338 }
339
340#if defined(EXTENDED_X11_TABLET_SUPPORT)
341
342 int numDevices = 0;
343 const XDeviceInfo *devices = XListInputDevices(x11Display, &numDevices);
344
345 if (devices != NULL) {
346 XID lastStylusSeen = 0;
347 XID lastEraserSeen = 0;
348 bool foundStylus = false;
349 bool foundEraser = false;
350
351 for (int i = 0; i < numDevices; i++) {
352
353 const XDeviceInfo *device = devices + i;
354 X11TabletDevice tabletDevice(device);
355
356 if (tabletDevice.mightBeTabletDevice()) {
357
358 tabletDevice.readSettingsFromConfig();
359
360 TQString lowerCaseName = tabletDevice.name().lower();
361
362 // Find the devices that TQt will use as its stylus and eraser devices.
363 if (!foundStylus || !foundEraser) {
364 if (lowerCaseName.startsWith("stylus") || lowerCaseName.startsWith("pen")) {
365 lastStylusSeen = device->id;
366 foundStylus = true;
367 }
368 else if (lowerCaseName.startsWith("eraser")) {
369 lastEraserSeen = device->id;
370 foundEraser = true;
371 }
372 }
373
374 X11TabletDeviceMap[device->id] = tabletDevice;
375
376 // Event types are device-independent. Store any
377 // the device supports.
378 if (tabletDevice.buttonPressEvent() >= 0) {
379 X11DeviceButtonPressEvent = tabletDevice.buttonPressEvent();
380 }
381 if (tabletDevice.buttonReleaseEvent() >= 0) {
382 X11DeviceButtonReleaseEvent = tabletDevice.buttonReleaseEvent();
383 }
384 if (tabletDevice.motionNotifyEvent() >= 0) {
385 X11DeviceMotionNotifyEvent = tabletDevice.motionNotifyEvent();
386 }
387 if (tabletDevice.proximityInEvent() >= 0) {
388 X11ProximityInEvent = tabletDevice.proximityInEvent();
389 }
390 if (tabletDevice.proximityOutEvent() >= 0) {
391 X11ProximityOutEvent = tabletDevice.proximityOutEvent();
392 }
393 }
394 }
395
396 // Allocate input devices.
397 for (X11XIDTabletDeviceMap::iterator it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) {
398
399 X11TabletDevice& tabletDevice = (*it).second;
400
401 if (foundStylus && tabletDevice.id() == lastStylusSeen) {
402 tabletDevice.setInputDevice(KisInputDevice::stylus());
403 } else if (foundEraser && tabletDevice.id() == lastEraserSeen) {
404 tabletDevice.setInputDevice(KisInputDevice::eraser());
405 } else {
406 tabletDevice.setInputDevice(KisInputDevice::allocateInputDevice());
407 }
408 }
409
410 XFreeDeviceList(const_cast<XDeviceInfo *>(devices));
411 }
412#endif // EXTENDED_X11_TABLET_SUPPORT
413}
414
415TQt::ButtonState KisCanvasWidget::translateX11ButtonState(int state)
416{
417 int buttonState = 0;
418
419 if (state & Button1Mask)
420 buttonState |= TQt::LeftButton;
421 if (state & Button2Mask)
422 buttonState |= TQt::MidButton;
423 if (state & Button3Mask)
424 buttonState |= TQt::RightButton;
425 if (state & ShiftMask)
426 buttonState |= TQt::ShiftButton;
427 if (state & ControlMask)
428 buttonState |= TQt::ControlButton;
429 if (state & X11AltMask)
430 buttonState |= TQt::AltButton;
431 if (state & X11MetaMask)
432 buttonState |= TQt::MetaButton;
433
434 return static_cast<TQt::ButtonState>(buttonState);
435}
436
437TQt::ButtonState KisCanvasWidget::translateX11Button(unsigned int X11Button)
438{
439 TQt::ButtonState qtButton;
440
441 switch (X11Button) {
442 case Button1:
443 qtButton = TQt::LeftButton;
444 break;
445 case Button2:
446 qtButton = TQt::MidButton;
447 break;
448 case Button3:
449 qtButton = TQt::RightButton;
450 break;
451 default:
452 qtButton = TQt::NoButton;
453 }
454
455 return qtButton;
456}
457
458#if defined(EXTENDED_X11_TABLET_SUPPORT)
459
460KisCanvasWidget::X11TabletDevice::X11TabletDevice()
461{
462 m_mightBeTabletDevice = false;
463 m_inputDevice = KisInputDevice::unknown();
464 m_enabled = false;
465 m_xAxis = NoAxis;
466 m_yAxis = NoAxis;
467 m_pressureAxis = NoAxis;
468 m_xTiltAxis = NoAxis;
469 m_yTiltAxis = NoAxis;
470 m_wheelAxis = NoAxis;
471 m_toolIDAxis = NoAxis;
472 m_serialNumberAxis = NoAxis;
473 m_buttonPressEvent = -1;
474 m_buttonReleaseEvent = -1;
475 m_motionNotifyEvent = -1;
476 m_proximityInEvent = -1;
477 m_proximityOutEvent = -1;
478}
479
480KisCanvasWidget::X11TabletDevice::X11TabletDevice(const XDeviceInfo *deviceInfo)
481{
482 m_mightBeTabletDevice = false;
483 m_inputDevice = KisInputDevice::unknown();
484 m_enabled = false;
485 m_xAxis = NoAxis;
486 m_yAxis = NoAxis;
487 m_pressureAxis = NoAxis;
488 m_xTiltAxis = NoAxis;
489 m_yTiltAxis = NoAxis;
490 m_wheelAxis = NoAxis;
491 m_toolIDAxis = NoAxis;
492 m_serialNumberAxis = NoAxis;
493
494 m_deviceId = deviceInfo->id;
495 m_name = deviceInfo->name;
496
497 // Get the ranges of the valuators
498 XAnyClassPtr classInfo = const_cast<XAnyClassPtr>(deviceInfo->inputclassinfo);
499
500 for (int i = 0; i < deviceInfo->num_classes; i++) {
501
502 if (classInfo->c_class == ValuatorClass) {
503
504 const XValuatorInfo *valuatorInfo = reinterpret_cast<const XValuatorInfo *>(classInfo);
505
506 // Need at least x, y, and pressure.
507
508 if (valuatorInfo->num_axes >= 3) {
509
510 for (unsigned int axis = 0; axis < valuatorInfo->num_axes; axis++) {
511 m_axisInfo.append(valuatorInfo->axes[axis]);
512 }
513
514 m_mightBeTabletDevice = true;
515 }
516 }
517
518 classInfo = reinterpret_cast<XAnyClassPtr>(reinterpret_cast<char *>(classInfo) + classInfo->length);
519 }
520
521 // Determine the event types it supports. We're only interested in
522 // buttons and motion at the moment.
523 m_buttonPressEvent = -1;
524 m_buttonReleaseEvent = -1;
525 m_motionNotifyEvent = -1;
526 m_proximityInEvent = -1;
527 m_proximityOutEvent = -1;
528
529 m_XDevice = XOpenDevice(TQApplication::desktop()->x11Display(), m_deviceId);
530
531 if (m_XDevice != NULL) {
532 for (int i = 0; i < m_XDevice->num_classes; i++) {
533
534 XEventClass eventClass;
535
536 if (m_XDevice->classes[i].input_class == ButtonClass) {
537 DeviceButtonPress(m_XDevice, m_buttonPressEvent, eventClass);
538 m_eventClassList.append(eventClass);
539
540 DeviceButtonRelease(m_XDevice, m_buttonReleaseEvent, eventClass);
541 m_eventClassList.append(eventClass);
542 }
543 else
544 if (m_XDevice->classes[i].input_class == ValuatorClass) {
545 DeviceMotionNotify(m_XDevice, m_motionNotifyEvent, eventClass);
546 m_eventClassList.append(eventClass);
547 }
548 else
549 if (m_XDevice->classes[i].input_class == ProximityClass) {
550 ProximityIn(m_XDevice, m_proximityInEvent, eventClass);
551 m_eventClassList.append(eventClass);
552
553 ProximityOut(m_XDevice, m_proximityOutEvent, eventClass);
554 m_eventClassList.append(eventClass);
555 }
556 }
557
558 // Note: We don't XCloseXDevice() since TQt will have already opened
559 // it, and only one XCloseDevice() call closes it for all opens.
560 }
561
562 if (m_buttonPressEvent == -1 || m_buttonReleaseEvent == -1 || m_motionNotifyEvent == -1) {
563 m_mightBeTabletDevice = false;
564 }
565}
566
567void KisCanvasWidget::X11TabletDevice::setEnabled(bool enabled)
568{
569 m_enabled = enabled;
570}
571
572bool KisCanvasWidget::X11TabletDevice::enabled() const
573{
574 return m_enabled;
575}
576
577TQ_INT32 KisCanvasWidget::X11TabletDevice::numAxes() const
578{
579 return m_axisInfo.count();
580}
581
582void KisCanvasWidget::X11TabletDevice::setXAxis(TQ_INT32 axis)
583{
584 m_xAxis = axis;
585}
586
587void KisCanvasWidget::X11TabletDevice::setYAxis(TQ_INT32 axis)
588{
589 m_yAxis = axis;
590}
591
592void KisCanvasWidget::X11TabletDevice::setPressureAxis(TQ_INT32 axis)
593{
594 m_pressureAxis = axis;
595}
596
597void KisCanvasWidget::X11TabletDevice::setXTiltAxis(TQ_INT32 axis)
598{
599 m_xTiltAxis = axis;
600}
601
602void KisCanvasWidget::X11TabletDevice::setYTiltAxis(TQ_INT32 axis)
603{
604 m_yTiltAxis = axis;
605}
606
607void KisCanvasWidget::X11TabletDevice::setWheelAxis(TQ_INT32 axis)
608{
609 m_wheelAxis = axis;
610}
611
612void KisCanvasWidget::X11TabletDevice::setToolIDAxis(TQ_INT32 axis)
613{
614 m_toolIDAxis = axis;
615}
616
617void KisCanvasWidget::X11TabletDevice::setSerialNumberAxis(TQ_INT32 axis)
618{
619 m_serialNumberAxis = axis;
620}
621
622TQ_INT32 KisCanvasWidget::X11TabletDevice::xAxis() const
623{
624 return m_xAxis;
625}
626
627TQ_INT32 KisCanvasWidget::X11TabletDevice::yAxis() const
628{
629 return m_yAxis;
630}
631
632TQ_INT32 KisCanvasWidget::X11TabletDevice::pressureAxis() const
633{
634 return m_pressureAxis;
635}
636
637TQ_INT32 KisCanvasWidget::X11TabletDevice::xTiltAxis() const
638{
639 return m_xTiltAxis;
640}
641
642TQ_INT32 KisCanvasWidget::X11TabletDevice::yTiltAxis() const
643{
644 return m_yTiltAxis;
645}
646
647TQ_INT32 KisCanvasWidget::X11TabletDevice::wheelAxis() const
648{
649 return m_wheelAxis;
650}
651
652TQ_INT32 KisCanvasWidget::X11TabletDevice::toolIDAxis() const
653{
654 return m_toolIDAxis;
655}
656
657TQ_INT32 KisCanvasWidget::X11TabletDevice::serialNumberAxis() const
658{
659 return m_serialNumberAxis;
660}
661
662void KisCanvasWidget::X11TabletDevice::readSettingsFromConfig()
663{
664 KisConfig cfg;
665
666 m_enabled = cfg.tabletDeviceEnabled(m_name);
667
668 m_xAxis = cfg.tabletDeviceAxis(m_name, "XAxis", DefaultAxis);
669 m_yAxis = cfg.tabletDeviceAxis(m_name, "YAxis", DefaultAxis);
670 m_pressureAxis = cfg.tabletDeviceAxis(m_name, "PressureAxis", DefaultAxis);
671 m_xTiltAxis = cfg.tabletDeviceAxis(m_name, "XTiltAxis", DefaultAxis);
672 m_yTiltAxis = cfg.tabletDeviceAxis(m_name, "YTiltAxis", DefaultAxis);
673 m_wheelAxis = cfg.tabletDeviceAxis(m_name, "WheelAxis", DefaultAxis);
674 m_toolIDAxis = cfg.tabletDeviceAxis(m_name, "ToolIDAxis", DefaultAxis);
675 m_serialNumberAxis = cfg.tabletDeviceAxis(m_name, "SerialNumberAxis", DefaultAxis);
676
677 if (!m_enabled && m_xAxis == DefaultAxis && m_yAxis == DefaultAxis && m_pressureAxis == DefaultAxis &&
678 m_xTiltAxis == DefaultAxis && m_yTiltAxis == DefaultAxis && m_wheelAxis == DefaultAxis &&
679 m_toolIDAxis == DefaultAxis && m_serialNumberAxis == DefaultAxis) {
680 // This is the first time this device has been seen. Set up default values, assuming
681 // it's a Wacom pad.
682 m_xAxis = 0;
683 m_yAxis = 1;
684 m_pressureAxis = 2;
685
686 if (m_axisInfo.count() >= 4) {
687 m_xTiltAxis = 3;
688 } else {
689 m_xTiltAxis = NoAxis;
690 }
691
692 if (m_axisInfo.count() >= 5) {
693 m_yTiltAxis = 4;
694 } else {
695 m_yTiltAxis = NoAxis;
696 }
697
698 if (m_axisInfo.count() >= 6) {
699 m_wheelAxis = 5;
700 } else {
701 m_wheelAxis = NoAxis;
702 }
703
704 // Available since driver version 0.7.2.
705 if (m_axisInfo.count() >= 7) {
706 m_toolIDAxis = 6;
707 } else {
708 m_toolIDAxis = NoAxis;
709 }
710
711 if (m_axisInfo.count() >= 8) {
712 m_serialNumberAxis = 7;
713 } else {
714 m_serialNumberAxis = NoAxis;
715 }
716 }
717}
718
719void KisCanvasWidget::X11TabletDevice::writeSettingsToConfig()
720{
721 KisConfig cfg;
722
723 cfg.setTabletDeviceEnabled(m_name, m_enabled);
724
725 cfg.setTabletDeviceAxis(m_name, "XAxis", m_xAxis);
726 cfg.setTabletDeviceAxis(m_name, "YAxis", m_yAxis);
727 cfg.setTabletDeviceAxis(m_name, "PressureAxis", m_pressureAxis);
728 cfg.setTabletDeviceAxis(m_name, "XTiltAxis", m_xTiltAxis);
729 cfg.setTabletDeviceAxis(m_name, "YTiltAxis", m_yTiltAxis);
730 cfg.setTabletDeviceAxis(m_name, "WheelAxis", m_wheelAxis);
731 cfg.setTabletDeviceAxis(m_name, "ToolIDAxis", m_toolIDAxis);
732 cfg.setTabletDeviceAxis(m_name, "SerialNumberAxis", m_serialNumberAxis);
733}
734
735void KisCanvasWidget::X11TabletDevice::enableEvents(TQWidget *widget) const
736{
737 if (!m_eventClassList.isEmpty()) {
738 int result = XSelectExtensionEvent(widget->x11AppDisplay(), widget->handle(),
739 const_cast<XEventClass*>(&m_eventClassList[0]),
740 m_eventClassList.count());
741
742 if (result != Success) {
743 kdDebug(41001) << "Failed to select extension events for " << m_name << endl;
744 }
745 }
746}
747
748double KisCanvasWidget::X11TabletDevice::translateAxisValue(int value, const XAxisInfo& axisInfo) const
749{
750 int axisRange = axisInfo.max_value - axisInfo.min_value;
751 double translatedValue = 0;
752
753 if (axisRange != 0) {
754 translatedValue = (static_cast<double>(value) - axisInfo.min_value) / axisRange;
755 if (axisInfo.min_value < 0) {
756 translatedValue -= 0.5;
757 }
758 }
759
760 return translatedValue;
761}
762
763KisCanvasWidget::X11TabletDevice::State::State(const KisPoint& pos, double pressure, const KisVector2D& tilt, double wheel,
764 TQ_UINT32 toolID, TQ_UINT32 serialNumber)
765 : m_pos(pos),
766 m_pressure(pressure),
767 m_tilt(tilt),
768 m_wheel(wheel),
769 m_toolID(toolID),
770 m_serialNumber(serialNumber)
771{
772}
773
774KisCanvasWidget::X11TabletDevice::State KisCanvasWidget::X11TabletDevice::translateAxisData(const int *axisData) const
775{
776 KisPoint pos(0, 0);
777
778 if (m_xAxis != NoAxis && m_yAxis != NoAxis) {
779 pos = KisPoint(translateAxisValue(axisData[m_xAxis], m_axisInfo[m_xAxis]),
780 translateAxisValue(axisData[m_yAxis], m_axisInfo[m_yAxis]));
781 }
782
783 double pressure = PRESSURE_DEFAULT;
784
785 if (m_pressureAxis != NoAxis) {
786 pressure = translateAxisValue(axisData[m_pressureAxis], m_axisInfo[m_pressureAxis]);
787 }
788
789 KisVector2D tilt = KisVector2D(0, 0);
790 TQ_UINT32 toolID = 0;
791 TQ_UINT32 serialNumber = 0;
792
793 if (m_xTiltAxis != NoAxis) {
794 // Latest wacom driver returns the tool id and serial number in
795 // the upper 16 bits of the x and y tilts and wheel.
796 int xTiltAxisValue = (TQ_INT16)(axisData[m_xTiltAxis] & 0xffff);
797 toolID = ((TQ_UINT32)axisData[m_xTiltAxis] >> 16) & 0xffff;
798
799 tilt.setX(translateAxisValue(xTiltAxisValue, m_axisInfo[m_xTiltAxis]));
800 }
801
802 if (m_yTiltAxis != NoAxis) {
803 int yTiltAxisValue = (TQ_INT16)(axisData[m_yTiltAxis] & 0xffff);
804 serialNumber = (TQ_UINT32)axisData[m_yTiltAxis] & 0xffff0000;
805
806 tilt.setY(translateAxisValue(yTiltAxisValue, m_axisInfo[m_yTiltAxis]));
807 }
808
809 double wheel = 0;
810
811 if (m_wheelAxis != NoAxis) {
812 int wheelAxisValue = (TQ_INT16)(axisData[m_wheelAxis] & 0xffff);
813 serialNumber |= ((TQ_UINT32)axisData[m_wheelAxis] >> 16) & 0xffff;
814
815 wheel = translateAxisValue(wheelAxisValue, m_axisInfo[m_wheelAxis]);
816 }
817
818 //TQString ids;
819 //ids.sprintf("Tool ID: %8x Serial Number: %8x", toolID, serialNumber);
820
821 return State(pos, pressure, tilt, wheel, toolID, serialNumber);
822}
823
824KisCanvasWidget::X11XIDTabletDeviceMap& KisCanvasWidget::tabletDeviceMap()
825{
826 return X11TabletDeviceMap;
827}
828
829void KisCanvasWidget::selectTabletDeviceEvents(TQWidget *widget)
830{
831 for (X11XIDTabletDeviceMap::const_iterator it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) {
832
833 const X11TabletDevice& device = (*it).second;
834
835 if (device.enabled()) {
836 device.enableEvents(widget);
837 }
838 }
839}
840
841#endif // EXTENDED_X11_TABLET_SUPPORT
842
843bool KisCanvasWidget::x11Event(XEvent *event, Display *x11Display, WId winId, TQPoint widgetOriginPos)
844{
845 if (event->type == MotionNotify) {
846 // Mouse move
847 if (!m_enableMoveEventCompressionHint) {
848
849 XMotionEvent motion = event->xmotion;
850 TQPoint globalPos(motion.x_root, motion.y_root);
851
852 if (globalPos.x() != m_lastRootX || globalPos.y() != m_lastRootY) {
853
854 int state = translateX11ButtonState(motion.state);
855 TQPoint pos(motion.x, motion.y);
856 TQMouseEvent e(TQEvent::MouseMove, pos, globalPos, TQt::NoButton, state);
857
858 widgetGotMouseMoveEvent(&e);
859 }
860
861 m_lastRootX = globalPos.x();
862 m_lastRootY = globalPos.y();
863
864 return true;
865 }
866 else {
867 return false;
868 }
869 }
870 else
871#if defined(EXTENDED_X11_TABLET_SUPPORT)
872 if (event->type == X11DeviceMotionNotifyEvent || event->type == X11DeviceButtonPressEvent || event->type == X11DeviceButtonReleaseEvent) {
873 // Tablet event.
874 int deviceId;
875 const int *axisData;
876 TQt::ButtonState button;
877 TQt::ButtonState buttonState;
878
879 if (event->type == X11DeviceMotionNotifyEvent) {
880 // Tablet move
881 const XDeviceMotionEvent *motion = reinterpret_cast<const XDeviceMotionEvent *>(event);
882 XEvent mouseEvent;
883
884 // Look for an accompanying core event.
885 if (XCheckTypedWindowEvent(x11Display, winId, MotionNotify, &mouseEvent)) {
886 if (motion->time == mouseEvent.xmotion.time) {
887 // Do nothing
888 } else {
889 XPutBackEvent(x11Display, &mouseEvent);
890 }
891 }
892
893 if (m_enableMoveEventCompressionHint) {
894 while (true) {
895 // Look for another motion notify in the queue and skip
896 // to that if found.
897 if (!XCheckTypedWindowEvent(x11Display, winId, X11DeviceMotionNotifyEvent, &mouseEvent)) {
898 break;
899 }
900
901 motion = reinterpret_cast<const XDeviceMotionEvent *>(&mouseEvent);
902
903 XEvent coreMotionEvent;
904
905 // Look for an accompanying core event.
906 if (!XCheckTypedWindowEvent(x11Display, winId, MotionNotify, &coreMotionEvent)) {
907 // Do nothing
908 }
909 }
910 }
911
912 deviceId = motion->deviceid;
913 axisData = motion->axis_data;
914 button = TQt::NoButton;
915 buttonState = translateX11ButtonState(motion->state);
916 }
917 else
918 if (event->type == X11DeviceButtonPressEvent) {
919 // Tablet button press
920 const XDeviceButtonPressedEvent *buttonPressed = reinterpret_cast<const XDeviceButtonPressedEvent *>(event);
921 deviceId = buttonPressed->deviceid;
922 axisData = buttonPressed->axis_data;
923 button = translateX11Button(buttonPressed->button);
924 buttonState = translateX11ButtonState(buttonPressed->state);
925
926 if (TQApplication::activePopupWidget() == 0) {
927 XEvent mouseEvent;
928
929 // Look for and swallow an accompanying core event, but only if there's
930 // no active popup, as that needs to see it.
931 if (XCheckTypedWindowEvent(x11Display, winId, ButtonPress, &mouseEvent)) {
932 if (buttonPressed->time == mouseEvent.xbutton.time) {
933 // Do nothing
934 }
935 else {
936 XPutBackEvent(x11Display, &mouseEvent);
937 }
938 }
939 }
940 }
941 else {
942 // Tablet button release
943 const XDeviceButtonReleasedEvent *buttonReleased = reinterpret_cast<const XDeviceButtonReleasedEvent *>(event);
944 deviceId = buttonReleased->deviceid;
945 axisData = buttonReleased->axis_data;
946 button = translateX11Button(buttonReleased->button);
947 buttonState = translateX11ButtonState(buttonReleased->state);
948
949 if (TQApplication::activePopupWidget() == 0) {
950 XEvent mouseEvent;
951
952 // Look for and swallow an accompanying core event, but only if there's
953 // no active popup, as that needs to see it.
954 if (XCheckTypedWindowEvent(x11Display, winId, ButtonRelease, &mouseEvent)) {
955 if (buttonReleased->time == mouseEvent.xbutton.time) {
956 // Do nothing
957 }
958 else {
959 XPutBackEvent(x11Display, &mouseEvent);
960 }
961 }
962 }
963 }
964
965 X11XIDTabletDeviceMap::const_iterator it = X11TabletDeviceMap.find(deviceId);
966
967 if (it != X11TabletDeviceMap.end()) {
968
969 const X11TabletDevice& tabletDevice = (*it).second;
970
971 if (tabletDevice.enabled()) {
972 X11TabletDevice::State deviceState = tabletDevice.translateAxisData(axisData);
973
974 // Map normalised position coordinates to screen coordinates
975 TQDesktopWidget *desktop = TQApplication::desktop();
976 KisPoint globalPos(deviceState.pos().x() * desktop->width(), deviceState.pos().y() * desktop->height());
977 // Convert screen coordinates to widget coordinates
978 KisPoint pos = globalPos - KoPoint( widgetOriginPos );
979
980 // Map tilt to -60 - +60 degrees
981 KisVector2D tilt(deviceState.tilt().x() * 60, deviceState.tilt().y() * 60);
982
983 if (event->type == X11DeviceMotionNotifyEvent) {
984 KisMoveEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), buttonState);
985 translateTabletEvent(&e);
986 }
987 else
988 if (event->type == X11DeviceButtonPressEvent) {
989 KisButtonPressEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), button, buttonState);
990 translateTabletEvent(&e);
991 }
992 else {
993 KisButtonReleaseEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), button, buttonState);
994 translateTabletEvent(&e);
995 }
996 }
997
998 // Consume the event even if the device is disabled otherwise TQt will
999 // process it and send a TQTabletEvent.
1000 return true;
1001 }
1002 else {
1003 return false;
1004 }
1005 }
1006 else
1007#endif // EXTENDED_X11_TABLET_SUPPORT
1008 {
1009 return false;
1010 }
1011}
1012
1013#if defined(EXTENDED_X11_TABLET_SUPPORT)
1014
1015KisInputDevice KisCanvasWidget::findActiveInputDevice()
1016{
1017 X11XIDTabletDeviceMap::const_iterator it;
1018
1019 for (it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) {
1020 const X11TabletDevice& tabletDevice = (*it).second;
1021
1022 XDeviceState *deviceState = XQueryDeviceState(TQApplication::desktop()->x11Display(),
1023 tabletDevice.xDevice());
1024
1025 // If your the laptop sleeps, and you remove the mouse from the usb
1026 // port, then on wake-up Chalk can crash because the above call will
1027 // return 0.
1028 if (!deviceState) continue;
1029
1030 const XInputClass *inputClass = deviceState->data;
1031 bool deviceIsInProximity = false;
1032
1033 for (int i = 0; i < deviceState->num_classes; i++) {
1034
1035 if (inputClass->c_class == ValuatorClass) {
1036
1037 const XValuatorState *valuatorState = reinterpret_cast<const XValuatorState *>(inputClass);
1038
1039 if ((valuatorState->mode & ProximityState) == InProximity) {
1040 deviceIsInProximity = true;
1041 break;
1042 }
1043 }
1044
1045 inputClass = reinterpret_cast<const XInputClass *>(reinterpret_cast<const char *>(inputClass) + inputClass->length);
1046 }
1047
1048 XFreeDeviceState(deviceState);
1049
1050 if (deviceIsInProximity && tabletDevice.enabled()) {
1051 return tabletDevice.inputDevice();
1052 }
1053 }
1054
1055 return KisInputDevice::mouse();
1056}
1057
1058#endif // EXTENDED_X11_TABLET_SUPPORT
1059
1060
1061#endif // TQ_WS_X11
1062
1063/*************************************************************************/
1064
1065#define TQPAINTDEVICE_CANVAS_WIDGET false
1066#define OPENGL_CANVAS_WIDGET true
1067
1068KisCanvas::KisCanvas(TQWidget *parent, const char *name)
1069{
1070 m_parent = parent;
1071 m_name = name;
1072 m_enableMoveEventCompressionHint = false;
1073 m_canvasWidget = 0;
1074 m_useOpenGL = false;
1075 createCanvasWidget(TQPAINTDEVICE_CANVAS_WIDGET);
1076}
1077
1078KisCanvas::~KisCanvas()
1079{
1080 delete m_canvasWidget;
1081}
1082
1083#ifdef HAVE_GL
1084void KisCanvas::createCanvasWidget(bool useOpenGL, TQGLWidget *sharedContextWidget)
1085#else
1086void KisCanvas::createCanvasWidget(bool useOpenGL)
1087#endif
1088{
1089 delete m_canvasWidget;
1090
1091#ifndef HAVE_GL
1092 useOpenGL = false;
1093#else
1094 if (useOpenGL && !TQGLFormat::hasOpenGL()) {
1095 kdDebug(41001) << "Tried to create OpenGL widget when system doesn't have OpenGL\n";
1096 useOpenGL = false;
1097 }
1098
1099 if (useOpenGL) {
1100 m_canvasWidget = new KisOpenGLCanvasWidget(m_parent, m_name.latin1(), sharedContextWidget);
1101 } else
1102#endif
1103 {
1104 m_canvasWidget = new KisTQPaintDeviceCanvasWidget(m_parent, m_name.latin1());
1105 }
1106
1107 m_useOpenGL = useOpenGL;
1108
1109 TQ_CHECK_PTR(m_canvasWidget);
1110 TQWidget *widget = dynamic_cast<TQWidget *>(m_canvasWidget);
1111
1112 widget->setBackgroundMode(TQWidget::NoBackground);
1113 widget->setMouseTracking(true);
1114 widget->setAcceptDrops(true);
1115 m_canvasWidget->enableMoveEventCompressionHint(m_enableMoveEventCompressionHint);
1116
1117#if defined(EXTENDED_X11_TABLET_SUPPORT)
1118 selectTabletDeviceEvents();
1119#endif
1120
1121 connect(m_canvasWidget, TQ_SIGNAL(sigGotPaintEvent(TQPaintEvent *)), TQ_SIGNAL(sigGotPaintEvent(TQPaintEvent *)));
1122 connect(m_canvasWidget, TQ_SIGNAL(sigGotEnterEvent(TQEvent*)), TQ_SIGNAL(sigGotEnterEvent(TQEvent*)));
1123 connect(m_canvasWidget, TQ_SIGNAL(sigGotLeaveEvent(TQEvent*)), TQ_SIGNAL(sigGotLeaveEvent(TQEvent*)));
1124 connect(m_canvasWidget, TQ_SIGNAL(sigGotMouseWheelEvent(TQWheelEvent*)), TQ_SIGNAL(sigGotMouseWheelEvent(TQWheelEvent*)));
1125 connect(m_canvasWidget, TQ_SIGNAL(sigGotKeyPressEvent(TQKeyEvent*)), TQ_SIGNAL(sigGotKeyPressEvent(TQKeyEvent*)));
1126 connect(m_canvasWidget, TQ_SIGNAL(sigGotKeyReleaseEvent(TQKeyEvent*)), TQ_SIGNAL(sigGotKeyReleaseEvent(TQKeyEvent*)));
1127 connect(m_canvasWidget, TQ_SIGNAL(sigGotDragEnterEvent(TQDragEnterEvent*)), TQ_SIGNAL(sigGotDragEnterEvent(TQDragEnterEvent*)));
1128 connect(m_canvasWidget, TQ_SIGNAL(sigGotDropEvent(TQDropEvent*)), TQ_SIGNAL(sigGotDropEvent(TQDropEvent*)));
1129 connect(m_canvasWidget, TQ_SIGNAL(sigGotMoveEvent(KisMoveEvent *)), TQ_SIGNAL(sigGotMoveEvent(KisMoveEvent *)));
1130 connect(m_canvasWidget, TQ_SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent *)), TQ_SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent *)));
1131 connect(m_canvasWidget, TQ_SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent *)), TQ_SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent *)));
1132 connect(m_canvasWidget, TQ_SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent *)), TQ_SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent *)));
1133}
1134
1135void KisCanvas::createTQPaintDeviceCanvas()
1136{
1137 createCanvasWidget(TQPAINTDEVICE_CANVAS_WIDGET);
1138}
1139
1140#ifdef HAVE_GL
1141void KisCanvas::createOpenGLCanvas(TQGLWidget *sharedContextWidget)
1142{
1143 createCanvasWidget(OPENGL_CANVAS_WIDGET, sharedContextWidget);
1144}
1145#endif
1146
1147bool KisCanvas::isOpenGLCanvas() const
1148{
1149 return m_useOpenGL;
1150}
1151
1152void KisCanvas::enableMoveEventCompressionHint(bool enableMoveCompression)
1153{
1154 m_enableMoveEventCompressionHint = enableMoveCompression;
1155 if (m_canvasWidget != 0) {
1156 m_canvasWidget->enableMoveEventCompressionHint(enableMoveCompression);
1157 }
1158}
1159
1160TQWidget *KisCanvas::TQPaintDeviceWidget() const
1161{
1162 if (m_useOpenGL) {
1163 return 0;
1164 } else {
1165 return dynamic_cast<TQWidget *>(m_canvasWidget);
1166 }
1167}
1168
1169#ifdef HAVE_GL
1170TQGLWidget *KisCanvas::OpenGLWidget() const
1171{
1172 if (m_useOpenGL) {
1173 return dynamic_cast<TQGLWidget *>(m_canvasWidget);
1174 } else {
1175 return 0;
1176 }
1177}
1178#endif
1179
1180KisCanvasWidgetPainter *KisCanvas::createPainter()
1181{
1182 Q_ASSERT(m_canvasWidget != 0);
1183 return m_canvasWidget->createPainter();
1184}
1185
1186KisCanvasWidget *KisCanvas::canvasWidget() const
1187{
1188 return m_canvasWidget;
1189}
1190
1191void KisCanvas::setGeometry(int x, int y, int width, int height)
1192{
1193 Q_ASSERT(m_canvasWidget);
1194 dynamic_cast<TQWidget *>(m_canvasWidget)->setGeometry(x, y, width, height);
1195}
1196
1197void KisCanvas::show()
1198{
1199 Q_ASSERT(m_canvasWidget);
1200 dynamic_cast<TQWidget *>(m_canvasWidget)->show();
1201}
1202
1203void KisCanvas::hide()
1204{
1205 Q_ASSERT(m_canvasWidget);
1206 dynamic_cast<TQWidget *>(m_canvasWidget)->hide();
1207}
1208
1209int KisCanvas::width() const
1210{
1211 Q_ASSERT(m_canvasWidget);
1212 return dynamic_cast<TQWidget *>(m_canvasWidget)->width();
1213}
1214
1215int KisCanvas::height() const
1216{
1217 Q_ASSERT(m_canvasWidget);
1218 return dynamic_cast<TQWidget *>(m_canvasWidget)->height();
1219}
1220
1221void KisCanvas::update()
1222{
1223 Q_ASSERT(m_canvasWidget);
1224 dynamic_cast<TQWidget *>(m_canvasWidget)->update();
1225}
1226
1227void KisCanvas::update(const TQRect& r)
1228{
1229 Q_ASSERT(m_canvasWidget);
1230 dynamic_cast<TQWidget *>(m_canvasWidget)->update(r);
1231}
1232
1233void KisCanvas::update(int x, int y, int width, int height)
1234{
1235 Q_ASSERT(m_canvasWidget);
1236 dynamic_cast<TQWidget *>(m_canvasWidget)->update(x, y, width, height);
1237}
1238
1239void KisCanvas::repaint()
1240{
1241 Q_ASSERT(m_canvasWidget);
1242 dynamic_cast<TQWidget *>(m_canvasWidget)->repaint();
1243}
1244
1245void KisCanvas::repaint(bool erase)
1246{
1247 Q_ASSERT(m_canvasWidget);
1248 dynamic_cast<TQWidget *>(m_canvasWidget)->repaint(erase);
1249}
1250
1251void KisCanvas::repaint(int x, int y, int width, int height, bool erase)
1252{
1253 Q_ASSERT(m_canvasWidget);
1254 dynamic_cast<TQWidget *>(m_canvasWidget)->repaint(x, y, width, height, erase);
1255}
1256
1257void KisCanvas::repaint(const TQRect& r, bool erase)
1258{
1259 Q_ASSERT(m_canvasWidget);
1260 dynamic_cast<TQWidget *>(m_canvasWidget)->repaint(r, erase);
1261}
1262
1263void KisCanvas::repaint(const TQRegion& r, bool erase)
1264{
1265 Q_ASSERT(m_canvasWidget);
1266 dynamic_cast<TQWidget *>(m_canvasWidget)->repaint(r, erase);
1267}
1268
1269bool KisCanvas::isUpdatesEnabled() const
1270{
1271 Q_ASSERT(m_canvasWidget);
1272 return dynamic_cast<TQWidget *>(m_canvasWidget)->isUpdatesEnabled();
1273}
1274
1275void KisCanvas::setUpdatesEnabled(bool updatesEnabled)
1276{
1277 Q_ASSERT(m_canvasWidget);
1278 dynamic_cast<TQWidget *>(m_canvasWidget)->setUpdatesEnabled(updatesEnabled);
1279}
1280
1281void KisCanvas::updateGeometry()
1282{
1283 Q_ASSERT(m_canvasWidget);
1284 dynamic_cast<TQWidget *>(m_canvasWidget)->updateGeometry();
1285}
1286
1287void KisCanvas::setFocusPolicy(TQWidget::FocusPolicy focusPolicy)
1288{
1289 Q_ASSERT(m_canvasWidget);
1290 dynamic_cast<TQWidget *>(m_canvasWidget)->setFocusPolicy(focusPolicy);
1291}
1292
1293const TQCursor& KisCanvas::cursor() const
1294{
1295 Q_ASSERT(m_canvasWidget);
1296 return dynamic_cast<TQWidget *>(m_canvasWidget)->cursor();
1297}
1298
1299void KisCanvas::setCursor(const TQCursor& cursor)
1300{
1301 Q_ASSERT(m_canvasWidget);
1302 dynamic_cast<TQWidget *>(m_canvasWidget)->setCursor(cursor);
1303}
1304
1305#if defined(EXTENDED_X11_TABLET_SUPPORT)
1306void KisCanvas::selectTabletDeviceEvents()
1307{
1308 Q_ASSERT(m_canvasWidget);
1309 m_canvasWidget->selectTabletDeviceEvents();
1310}
1311#endif
1312
1313bool KisCanvas::cursorIsOverCanvas() const
1314{
1315 if (TQApplication::activePopupWidget() != 0) {
1316 return false;
1317 }
1318 if (TQApplication::activeModalWidget() != 0) {
1319 return false;
1320 }
1321
1322 TQWidget *canvasWidget = dynamic_cast<TQWidget *>(m_canvasWidget);
1323 Q_ASSERT(canvasWidget != 0);
1324
1325 if (canvasWidget) {
1326 if (TQApplication::widgetAt(TQCursor::pos(), true) == canvasWidget) {
1327 return true;
1328 }
1329 }
1330 return false;
1331}
1332
1333void KisCanvas::handleKeyEvent(TQEvent *e)
1334{
1335 TQKeyEvent *ke = dynamic_cast<TQKeyEvent *>(e);
1336
1337 Q_ASSERT(ke != 0);
1338
1339 if (ke) {
1340 TQWidget *canvasWidget = dynamic_cast<TQWidget *>(m_canvasWidget);
1341 Q_ASSERT(canvasWidget != 0);
1342
1343 if (canvasWidget) {
1344 canvasWidget->setFocus();
1345
1346 if (e->type() == TQEvent::KeyPress) {
1347 emit sigGotKeyPressEvent(ke);
1348 } else {
1349 emit sigGotKeyReleaseEvent(ke);
1350 }
1351 }
1352 }
1353}
1354
1355#include "kis_canvas.moc"
1356
A double-based point class that can return it's coordinates approximated to integers.
Definition kis_point.h:28