kmagzoomview.cpp 32.9 KB
Newer Older
Sarang Lakare's avatar
Sarang Lakare committed
1
2
3
4
/***************************************************************************
                          kmagview.cpp  -  description
                             -------------------
    begin                : Mon Feb 12 23:45:41 EST 2001
Sarang Lakare's avatar
Sarang Lakare committed
5
6
    copyright            : (C) 2001-2003 by Sarang Lakare
    email                : sarang#users.sourceforge.net
7
    copyright            : (C) 2003-2004 by Olaf Schmidt
8
    email                : ojschmidt@kde.org
9
10
    copyright            : (C) 2008 by Matthew Woehlke
    email                : mw_triad@users.sourceforge.net
Sebastian Sauer's avatar
Sebastian Sauer committed
11
12
    copyright              (C) 2010 Sebastian Sauer
    email                  sebsauer@kdab.com
Sarang Lakare's avatar
Sarang Lakare committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/


// application specific includes
#include "kmagzoomview.h"
27
#include "colorsim.h"
Sarang Lakare's avatar
Sarang Lakare committed
28
29

// include files for Qt
30
#include <QApplication>
Christoph Feck's avatar
Christoph Feck committed
31
32
#include <QBitmap>
#include <QDesktopWidget>
Christoph Feck's avatar
Christoph Feck committed
33
#include <QScrollBar>
34
#include <QScreen>
Laurent Montel's avatar
Laurent Montel committed
35
#include <QPainter>
Arto Hytönen's avatar
Arto Hytönen committed
36

37
// include files for KF5
Christoph Feck's avatar
Christoph Feck committed
38
39
#include <KLocalizedString>

40
41
#ifdef QAccessibilityClient_FOUND
#include <qaccessibilityclient/accessibleobject.h>
Allen Winter's avatar
Allen Winter committed
42
#endif
Sarang Lakare's avatar
Sarang Lakare committed
43

44
// include bitmaps for cursors
45
static const uchar left_ptr_bits[] = {
46
47
48
49
   0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00,
   0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01,
   0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00};

50
static const uchar left_ptrmsk_bits[] = {
51
52
53
54
   0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01,
   0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03,
   0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03};

55
static const uchar phand_bits[] = {
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
56
57
58
59
60
61
62
63
64
65
66
  0x00, 0x00, 0x00, 0x00,  0xfe, 0x01, 0x00, 0x00,  0x01, 0x02, 0x00, 0x00,
  0x7e, 0x04, 0x00, 0x00,  0x08, 0x08, 0x00, 0x00,  0x70, 0x08, 0x00, 0x00,
  0x08, 0x08, 0x00, 0x00,  0x70, 0x14, 0x00, 0x00,  0x08, 0x22, 0x00, 0x00,
  0x30, 0x41, 0x00, 0x00,  0xc0, 0x20, 0x00, 0x00,  0x40, 0x12, 0x00, 0x00,
  0x80, 0x08, 0x00, 0x00,  0x00, 0x05, 0x00, 0x00,  0x00, 0x02, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00 };
67
static const uchar phandm_bits[] = {
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
68
69
70
71
72
73
74
75
76
77
78
  0xfe, 0x01, 0x00, 0x00,  0xff, 0x03, 0x00, 0x00,  0xff, 0x07, 0x00, 0x00,
  0xff, 0x0f, 0x00, 0x00,  0xfe, 0x1f, 0x00, 0x00,  0xf8, 0x1f, 0x00, 0x00,
  0xfc, 0x1f, 0x00, 0x00,  0xf8, 0x3f, 0x00, 0x00,  0xfc, 0x7f, 0x00, 0x00,
  0xf8, 0xff, 0x00, 0x00,  0xf0, 0x7f, 0x00, 0x00,  0xe0, 0x3f, 0x00, 0x00,
  0xc0, 0x1f, 0x00, 0x00,  0x80, 0x0f, 0x00, 0x00,  0x00, 0x07, 0x00, 0x00,
  0x00, 0x02, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00 };
79
80


Sarang Lakare's avatar
Sarang Lakare committed
81
KMagZoomView::KMagZoomView(QWidget *parent, const char *name)
82
  : QAbstractScrollArea(parent),
83
    m_selRect(0, 0, 128, 128, this),
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
84
85
86
87
    m_grabTimer(parent),
    m_mouseViewTimer(parent),
    m_latestCursorPos(0,0),
    m_followMouse(false),
88
    m_followFocus(false),
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
89
90
    m_showMouse(1),
    m_zoom(1.0),
91
    m_rotation(0),
Sebastian Sauer's avatar
Sebastian Sauer committed
92
    m_colormode(0),
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
93
    m_fitToWindow(true)
Sarang Lakare's avatar
Sarang Lakare committed
94
{
95
  setObjectName( QLatin1String( name ));
96

97
  viewport()->setMouseTracking(true);
98
  viewport()->setAttribute(Qt::WA_NoSystemBackground, true);
99
  viewport()->setAutoFillBackground(false);
Laurent Montel's avatar
Laurent Montel committed
100
  viewport()->setFocusPolicy(Qt::StrongFocus);
101

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
102
  // init the zoom matrix
103
  setupMatrix();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
104
105
106
107

  m_ctrlKeyPressed = false;
  m_shiftKeyPressed = false;
  m_refreshSwitch = true;
Sarang Lakare's avatar
Sarang Lakare committed
108
  m_refreshSwitchStateOnHide = m_refreshSwitch;
109

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
110
111
112
113
  // set the refresh rate
  setRefreshRate(10);

  // connect it to grabFrame()
114
  connect(&m_grabTimer, &QTimer::timeout, this, &KMagZoomView::grabFrame);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
115
116
  // start the grabTimer
  m_grabTimer.start(static_cast<int>(1000.0/m_fps));
Sarang Lakare's avatar
Sarang Lakare committed
117

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
118
  // connect it to updateMouseView()
119
  connect(&m_mouseViewTimer, &QTimer::timeout, this, &KMagZoomView::updateMouseView);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
120
  // start the grabTimer @ 25 frames per second!
121
  m_mouseViewTimer.start(40);
122

Laurent Montel's avatar
Laurent Montel committed
123
  this->setWhatsThis( i18n("This is the main window which shows the contents of the\
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
124
 selected region. The contents will be magnified according to the zoom level that is set."));
125

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
126
  // different ways to show the cursor.
127
  m_showMouseTypes << QStringLiteral( "Hidden" ) << QStringLiteral( "Box" ) << QStringLiteral( "Arrow" ) << QStringLiteral( "Actual" );
Sarang Lakare's avatar
Sarang Lakare committed
128

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
129
130
  if(m_fitToWindow)
    fitToWindow();
131

132
#ifdef QAccessibilityClient_FOUND
133
  //subscribe to focus events from registry
134
  m_registry.subscribeEventListeners(QAccessibleClient::Registry::Focus | QAccessibleClient::Registry::TextCaretMoved);
135
#endif
Sarang Lakare's avatar
Sarang Lakare committed
136
137
138
139
140
141
}

KMagZoomView::~KMagZoomView()
{
}

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
int KMagZoomView::contentsX() const
{
  return horizontalScrollBar()->value();
}

int KMagZoomView::contentsY() const
{
  return verticalScrollBar()->value();
}

int KMagZoomView::contentsWidth() const
{
  return horizontalScrollBar()->pageStep();
}

int KMagZoomView::contentsHeight() const
{
  return verticalScrollBar()->pageStep();
}

int KMagZoomView::visibleWidth() const
{
  return viewport()->width();
}

int KMagZoomView::visibleHeight() const
{
  return viewport()->height();
}

void KMagZoomView::setContentsPos(int x, int y)
{
  horizontalScrollBar()->setValue(x);
  verticalScrollBar()->setValue(y);
}

178
179
180
181
182
183
184
void KMagZoomView::setupMatrix()
{
  m_zoomMatrix.reset();
  m_zoomMatrix.scale(m_zoom, m_zoom);
  m_zoomMatrix.rotate(m_rotation);
}

Sarang Lakare's avatar
Sarang Lakare committed
185
186
187
/**
 * This function will set/reset mouse following of grab window.
 */
188
void KMagZoomView::followMouse(bool follow)
Sarang Lakare's avatar
Sarang Lakare committed
189
{
190
191
  m_followMouse = follow;
  m_mouseMode = Normal;
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
192
  if(follow) {
193
194
    setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
195
  } else {
196
197
    setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
    setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
198
  }
Sarang Lakare's avatar
Sarang Lakare committed
199
200
}

201
#ifdef QAccessibilityClient_FOUND
202
203
204
205
206
207
208
209
210
211

void KMagZoomView::followBoth(bool follow)
{
    m_followBoth = follow;
    if(follow){
        m_followMouse = true;
        m_followFocus = false;
        setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
        setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);

212
213
214
215
        connect(&m_registry, SIGNAL(focusChanged(QAccessibleClient::AccessibleObject)),
                this, SLOT(focusChanged(QAccessibleClient::AccessibleObject)));
        connect(&m_registry, SIGNAL(textCaretMoved(QAccessibleClient::AccessibleObject,int)),
                this, SLOT(focusChanged(QAccessibleClient::AccessibleObject)));
216
217
218
219
    } else {
        setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
        setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOn);

220
        disconnect(this, SLOT(focusChanged(QAccessibleClient::AccessibleObject)));
221
222
223
    }
}

224
225
226
227
228
229
230
231
232
233
/**
 * This function will set/reset keyboard focus following of grab window.
 */
void KMagZoomView::followFocus(bool follow)
{
  if(m_followFocus == follow)
      return;
  m_followFocus = follow;
  m_mouseMode = Normal;
  if(follow) {
234
235
    setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
236

237
238
239
240
    connect(&m_registry,SIGNAL(focusChanged(QAccessibleClient::AccessibleObject)),
            this, SLOT(focusChanged(QAccessibleClient::AccessibleObject)));
    connect(&m_registry, SIGNAL(textCaretMoved(QAccessibleClient::AccessibleObject,int)),
            this, SLOT(focusChanged(QAccessibleClient::AccessibleObject)));
241
  } else {
242
243
    setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
    setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
244

245
    disconnect(this, SLOT(focusChanged(QAccessibleClient::AccessibleObject)));
246
247
248
  }
}

249
void KMagZoomView::focusChanged(const QAccessibleClient::AccessibleObject &object)
250
{
251
    m_oldFocus = object.focusPoint();
252
253
254
255
256
    if(m_followBoth && !m_selRect.contains(m_oldFocus)) {
        QCursor::setPos(m_oldFocus);
        m_followFocus = true;
        m_followMouse = false;
    }
257
}
258

259
#endif
260

Sarang Lakare's avatar
Sarang Lakare committed
261
262
263
/**
 * Called when the widget is hidden. Stop refresh when this happens.
 */
Sarang Lakare's avatar
Sarang Lakare committed
264
void KMagZoomView::hideEvent( QHideEvent* )
Sarang Lakare's avatar
Sarang Lakare committed
265
266
267
268
{
  // Save the state of the refresh switch.. the state will be restored
  // when showEvent is called
  m_refreshSwitchStateOnHide = m_refreshSwitch;
269

Sarang Lakare's avatar
Sarang Lakare committed
270
271
272
  // Check if refresh is ON
  if(m_refreshSwitch) {
    toggleRefresh();
273
  }
Sarang Lakare's avatar
Sarang Lakare committed
274
275
276
277
278
279
}


/**
 * Called when the widget is shown. Start refresh when this happens.
 */
Sarang Lakare's avatar
Sarang Lakare committed
280
void KMagZoomView::showEvent( QShowEvent* )
Sarang Lakare's avatar
Sarang Lakare committed
281
282
283
284
285
286
287
288
{
  // Check if refresh switch was ON when hide was called and if currently it is OFF
  if(m_refreshSwitchStateOnHide && !m_refreshSwitch) {
    // start the refresh in that case
    toggleRefresh();
  }
}

289
290
291
/**
 * Called when the widget is resized. Check if fitToWindow is active when this happens.
 */
292
void KMagZoomView::resizeEvent( QResizeEvent * e )
293
{
294
295
296
  horizontalScrollBar()->setRange(0, contentsWidth() - visibleWidth());
  verticalScrollBar()->setRange(0, contentsHeight() - visibleHeight());
  QAbstractScrollArea::resizeEvent(e);
297
  if(m_fitToWindow)
298
    fitToWindow();
299
}
Sarang Lakare's avatar
Sarang Lakare committed
300

Sarang Lakare's avatar
Sarang Lakare committed
301
/**
302
 * Called when the widget is to be repainted.
Sarang Lakare's avatar
Sarang Lakare committed
303
304
305
 *
 * @param p
 */
306
void KMagZoomView::paintEvent(QPaintEvent *e)
Sarang Lakare's avatar
Sarang Lakare committed
307
{
Christoph Feck's avatar
Christoph Feck committed
308
  if(m_coloredPixmap.isNull())
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
309
    return;
Sarang Lakare's avatar
Sarang Lakare committed
310

311
312
313
314
315
316
  QPainter p(viewport());
  int clipx = e->rect().x();
  int clipy = e->rect().x();
  int clipw = e->rect().width();
  int cliph = e->rect().height();

Laurent Montel's avatar
Laurent Montel committed
317
  // Paint empty areas Qt::black
318
  if (contentsX()+contentsWidth() < visibleWidth())
319
    p.fillRect (
320
        QRect (contentsX()+contentsWidth(), clipy, visibleWidth()-contentsX()-contentsWidth(), cliph)
321
        & e->rect(),
322
323
        Qt::black);
  if (contentsY()+contentsHeight() < visibleHeight())
324
    p.fillRect (
325
        QRect (clipx, contentsY()+contentsHeight(), clipw, visibleHeight()-contentsY()-contentsHeight())
326
        & e->rect(),
327
        Qt::black);
328

Christoph Feck's avatar
Christoph Feck committed
329
  p.translate(visibleWidth() / 2.0, visibleHeight() / 2.0);
Laurent Montel's avatar
Laurent Montel committed
330
  p.setWorldTransform(m_zoomMatrix, true);
Christoph Feck's avatar
Christoph Feck committed
331
332
  const double ratio = 0.5 / m_coloredPixmap.devicePixelRatio();
  p.translate(-m_coloredPixmap.width() * ratio, -m_coloredPixmap.height() * ratio);
Christoph Feck's avatar
Christoph Feck committed
333
  p.drawPixmap(QPoint(clipx-contentsX(), clipy-contentsY()), m_coloredPixmap);
334
  p.end();
335

336
337
  if (m_showMouse)
    paintMouseCursor(viewport(), calcMousePos (m_refreshSwitch));
Sarang Lakare's avatar
Sarang Lakare committed
338
339
}

340
341
342
343
/**
 * Draws the mouse cursor according to the current selection of the type of
 * mouse cursor to draw.
 */
344
void KMagZoomView::paintMouseCursor(QPaintDevice *dev, const QPoint &mousePos)
345
{
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
346
347
  if(!dev)
    return;
348
349
350
351

  // painter for the zoom view
  QPainter pz(dev);

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
352
353
354
    // How to show the mouse :

    switch(m_showMouse) {
355
    case 1:
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
356
357
      // 1. Square around the pixel
      pz.setPen(Qt::white);
358
#ifdef __GNUC__
359
#warning "Port Qt4 pz.setRasterOp(Qt::XorROP);";
Matthew Woehlke's avatar
Matthew Woehlke committed
360
#endif
Laurent Montel's avatar
Laurent Montel committed
361
      //pz.setRasterOp(Qt::XorROP);
362
      pz.drawRect(mousePos.x()-1, mousePos.y()-1, (int)m_zoom+2, (int)m_zoom+2);
363
364
      break;

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
365
366
367
368
    case 2:
    {
      // 2. Arrow cursor
      pz.setPen(Qt::black);
369
      pz.setBackground(Qt::white);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
370

371
372
      QPixmap sCursor(16, 16);
      QBitmap cursor = QBitmap::fromData( QSize(16,  16),  left_ptr_bits);
Stephan Kulow's avatar
Stephan Kulow committed
373
      QBitmap mask = QBitmap::fromData( QSize(16,  16),  left_ptrmsk_bits);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
374
      sCursor.setMask(mask);
375
376
377
378
379
380
      QPainter p(&sCursor);
      p.setPen(Qt::gray);
      p.drawPixmap(0, 0, mask);
      p.setPen(Qt::black);
      p.drawPixmap(0, 0, cursor);
      p.end();
Laurent Montel's avatar
Laurent Montel committed
381
      sCursor = sCursor.transformed(m_zoomMatrix);
382

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
383
      // since hot spot is at 3,1
384
385
386
387
388
389
390
391
      if (m_rotation == 0)
        pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
      else if (m_rotation == 90)
        pz.drawPixmap(mousePos.x()-(int)(16.0*m_zoom), mousePos.y()-(int)(3.0*m_zoom), sCursor);
      else if (m_rotation == 180)
        pz.drawPixmap(mousePos.x()-(int)(13.0*m_zoom), mousePos.y()-(int)(16.0*m_zoom), sCursor);
      else if (m_rotation == 270)
        pz.drawPixmap(mousePos.x()-(int)m_zoom, mousePos.y()-(int)(13.0*m_zoom), sCursor);
392
    }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
393
394
395
    break;

    case 3:
Matthew Woehlke's avatar
Matthew Woehlke committed
396
    {
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
397
398
      // 3. Actual cursor
      // Get the current cursor type
399
      QWidget *dummy  = QApplication::topLevelAt(QCursor::pos());
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
400
401
402
      if(!dummy)
        break;
      switch(this->cursor().shape())  {
Laurent Montel's avatar
Laurent Montel committed
403
			  case Qt::ArrowCursor :
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
404
405
406
         {
          // 2. Arrow cursor
          pz.setPen(Qt::black);
407
          pz.setBackground(Qt::white);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
408

Stephan Kulow's avatar
Stephan Kulow committed
409
410
          QBitmap sCursor = QBitmap::fromData( QSize(16,  16),  left_ptr_bits);
          QBitmap mask = QBitmap::fromData( QSize(16,  16),  left_ptrmsk_bits);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
411
          sCursor.setMask(mask);
Laurent Montel's avatar
Laurent Montel committed
412
          sCursor = sCursor.transformed(m_zoomMatrix);
413

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
414
          // since hot spot is at 3,1
415
          pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
416
        }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
417
418
        break;
        default:
Stephan Kulow's avatar
Stephan Kulow committed
419
420
          QBitmap sCursor = QBitmap::fromData( QSize(32,  32),  phand_bits);
          QBitmap mask = QBitmap::fromData( QSize(32,  32),  phandm_bits);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
421
          sCursor.setMask(mask);
422

423
          pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor);
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
424
425
        break;
      } // switch(cursor)
426
427
428


    }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
429
    break;
430

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
431
432
433
434
    default:
      // do not show anything
      break;
    } // switch(m_showMouse)
435
436
437
}


438
439
440
441
442
443
444
445
446
QPoint KMagZoomView::calcMousePos(bool updateMousePos)
{
  // get position of mouse wrt selRect
  if(updateMousePos) { // get a new position only if asked
    m_latestCursorPos = QCursor::pos();
    m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y());
  }

  // get coordinates of the pixel w.r.t. the zoomed pixmap
447
448
449
450
451
452
453
454
455
456
457
  if (m_rotation == 90)
    return QPoint ((int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom),
                   (int)((float)m_latestCursorPos.x()*m_zoom));
  else if (m_rotation == 180)
    return QPoint ((int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom),
                   (int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom));
  else if (m_rotation == 270)
    return QPoint ((int)((float)m_latestCursorPos.y()*m_zoom),
                   (int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom));
  else
    return QPoint ((int)((float)m_latestCursorPos.x()*m_zoom),
458
459
460
461
                   (int)((float)m_latestCursorPos.y()*m_zoom));
}


Sarang Lakare's avatar
Sarang Lakare committed
462
463
464
// MOUSE ACTIONS

/**
465
 * Called when mouse is clicked inside the window.
Sarang Lakare's avatar
Sarang Lakare committed
466
467
468
469
470
471
 *
 * @param e
 */
void KMagZoomView::mousePressEvent(QMouseEvent *e)
{
  switch(e->button()) {
Laurent Montel's avatar
Laurent Montel committed
472
  case Qt::LeftButton :
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
473
474
    if(m_ctrlKeyPressed) {
      // check if currently in resize mode
475
476
      // don't do anything if fitToWindow is enabled
      if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) {
477
478
479
480
        // set the mode to ResizeSelection
        m_mouseMode = ResizeSelection;

        // set mouse cursor to "resize all direction"
Laurent Montel's avatar
Laurent Montel committed
481
        setCursor(Qt::SizeAllCursor);
482
483
484
485
486

        // backup the old position
        m_oldMousePos.setX(e->globalX());
        m_oldMousePos.setY(e->globalY());

Sarang Lakare's avatar
Sarang Lakare committed
487
        // set the cursor position to the bottom-right of the selected region
488
489
490
491
492
        QCursor::setPos(m_selRect.bottomRight());

        // show the selection rectangle
        m_selRect.show();
      }
493
494
495
496
      else {
        // ignore this button press.. so it goes to the parent
        e->ignore();
      }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
497
    } else if(m_shiftKeyPressed) {
Sarang Lakare's avatar
Sarang Lakare committed
498
      // check if currently in move mode
499
500
      // don't do anything if follow mouse is enabled
      if ((m_mouseMode != MoveSelection) && !m_followMouse) {
Sarang Lakare's avatar
Sarang Lakare committed
501
502
503
        m_mouseMode = MoveSelection;

        // set mouse cursor to cross hair
Laurent Montel's avatar
Laurent Montel committed
504
        setCursor(Qt::CrossCursor);
Sarang Lakare's avatar
Sarang Lakare committed
505
506
507
508
509
510
511
512
513
514
515

        // backup the old position
        m_oldMousePos.setX(e->globalX());
        m_oldMousePos.setY(e->globalY());

        // set the cursor position to the center of the selected region
        QCursor::setPos(m_selRect.center());

        // show the selected rectangle
        m_selRect.show();
      }
516
517
518
519
      else {
        // ignore this button press.. so it goes to the parent
        e->ignore();
      }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
520
    } else {
521
      // check if currently in move mode
522
523
      // don't do anything if follow mouse is enabled
      if ((m_mouseMode != GrabSelection) && !m_followMouse) {
524
        m_mouseMode = GrabSelection;
Sarang Lakare's avatar
Sarang Lakare committed
525

526
        // set mouse cursor to hand
527
        setCursor(Qt::PointingHandCursor);
Sarang Lakare's avatar
Sarang Lakare committed
528

529
        // store the old position
Sarang Lakare's avatar
Sarang Lakare committed
530
531
532
        m_oldMousePos.setX(e->globalX());
        m_oldMousePos.setY(e->globalY());

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
533
        m_oldCenter = m_selRect.center();
Sarang Lakare's avatar
Sarang Lakare committed
534

535
        // show the selected rectangle
Sarang Lakare's avatar
Sarang Lakare committed
536
537
        m_selRect.show();
      }
538
539
540
541
      else {
        // ignore this button press.. so it goes to the parent
        e->ignore();
      }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
542
    }
Sarang Lakare's avatar
Sarang Lakare committed
543
544
    break;

545
  case Qt::MiddleButton :
546
547
548
    // check if currently in move mode
    // don't do anything if follow mouse is enabled
    if ((m_mouseMode != MoveSelection) && !m_followMouse) {
Sarang Lakare's avatar
Sarang Lakare committed
549
550
551
      m_mouseMode = MoveSelection;

      // set mouse cursor to cross hair
Laurent Montel's avatar
Laurent Montel committed
552
      setCursor(Qt::CrossCursor);
Sarang Lakare's avatar
Sarang Lakare committed
553
554
555
556
557
558
559
560
561
562

      // backup the old position
      m_oldMousePos.setX(e->globalX());
      m_oldMousePos.setY(e->globalY());

      // set the cursor position to the center of the selected region
      QCursor::setPos(m_selRect.center());

      // show the selected rectangle
      m_selRect.show();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
563
    }
564
565
566
567
    else {
      // ignore this button press.. so it goes to the parent
      e->ignore();
    }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
568
    break;
Sarang Lakare's avatar
Sarang Lakare committed
569
570
  // do nothing
  default:
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
571
572
573
    // ignore this button press.. so it goes to the parent
    e->ignore();
    break;
Sarang Lakare's avatar
Sarang Lakare committed
574
575
576
577
578
579
580
581
582
583
584
585
  }
}


/**
 * Called when a mouse button is released
 *
 * @param e
 */
void KMagZoomView::mouseReleaseEvent(QMouseEvent *e)
{
  switch(e->button()) {
Laurent Montel's avatar
Laurent Montel committed
586
  case Qt::LeftButton :
587
  case Qt::MiddleButton :
588
589
590
591
592
593
594
595
    // check if currently in move mode
    if(m_mouseMode == MoveSelection) {
      // hide the selection window
      m_selRect.hide();
      // set the mouse mode to normal
      m_mouseMode = Normal;

      // restore the cursor shape
Laurent Montel's avatar
Laurent Montel committed
596
      setCursor(Qt::ArrowCursor);
597
598
599
600
601
602
603
604
605
606

      // restore the cursor position
      QCursor::setPos(m_oldMousePos);
    } else if(m_mouseMode == ResizeSelection) {
      // hide the selection window
      m_selRect.hide();
      // set the mouse mode to normal
      m_mouseMode = Normal;

      // restore the cursor shape
Laurent Montel's avatar
Laurent Montel committed
607
      setCursor(Qt::ArrowCursor);
608
609
610
611
612
613
614
615
616
617
618

      // restore the cursor position
      QCursor::setPos(m_oldMousePos);
    } else if(m_mouseMode == GrabSelection) {
      // hide the selection window
      m_selRect.hide();

      // set the mouse mode to normal
      m_mouseMode = Normal;

      // restore the cursor shape
Laurent Montel's avatar
Laurent Montel committed
619
      setCursor(Qt::ArrowCursor);
Matthew Woehlke's avatar
Matthew Woehlke committed
620
    }
Sarang Lakare's avatar
Sarang Lakare committed
621
622
    break;

Laurent Montel's avatar
Laurent Montel committed
623
  case Qt::RightButton :
Sarang Lakare's avatar
Sarang Lakare committed
624
    break;
Laurent Montel's avatar
Laurent Montel committed
625
  case Qt::NoButton :
Sarang Lakare's avatar
Sarang Lakare committed
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
    break;

  // do nothing
  default:
    ;
  }
}


/**
 * Called when mouse is moved inside the window
 *
 * @param e
 */
void KMagZoomView::mouseMoveEvent(QMouseEvent *e)
{
642
  if(m_mouseMode == ResizeSelection) {
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
643
    // In resize selection mode
Sarang Lakare's avatar
Sarang Lakare committed
644
645
646
647
    // set the current mouse position as the bottom, right corner
    m_selRect.setRight(e->globalX());
    m_selRect.setBottom(e->globalY());
    m_selRect.update();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
    grabFrame();
  } else if(m_mouseMode == MoveSelection) {
     QPoint newCenter;

    // set new center to be the current mouse position
    newCenter = e->globalPos();

    // make sure the mouse position is not taking the grab window outside
    // the display
    if(newCenter.x() < m_selRect.width()/2) {
      // set X to the minimum possible X
      newCenter.setX(m_selRect.width()/2);
    } else if(newCenter.x() >=  QApplication::desktop()->width()-m_selRect.width()/2) {
      // set X to the maximum possible X
      newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
    }

    if(newCenter.y() < m_selRect.height()/2) {
      // set Y to the minimum possible Y
      newCenter.setY(m_selRect.height()/2);
    } else if(newCenter.y() >=  QApplication::desktop()->height()-m_selRect.height()/2) {
      // set Y to the maximum possible Y
      newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
    }
    // move to the new center
    m_selRect.moveCenter(newCenter);
Sarang Lakare's avatar
Sarang Lakare committed
674
675
    // update the grab rectangle display
    m_selRect.update();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
    grabFrame();
  } else if(m_mouseMode == GrabSelection) {
     QPoint newPos;

    // get new position
    newPos = e->globalPos();

    QPoint delta = (newPos - m_oldMousePos)/m_zoom;
    QPoint newCenter = m_oldCenter-delta;

    // make sure the mouse position is not taking the grab window outside
    // the display
    if(newCenter.x() < m_selRect.width()/2) {
      // set X to the minimum possible X
      newCenter.setX(m_selRect.width()/2);
    } else if(newCenter.x() >=  QApplication::desktop()->width()-m_selRect.width()/2) {
      // set X to the maximum possible X
      newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
    }

    if(newCenter.y() < m_selRect.height()/2) {
      // set Y to the minimum possible Y
      newCenter.setY(m_selRect.height()/2);
    } else if(newCenter.y() >=  QApplication::desktop()->height()-m_selRect.height()/2) {
      // set Y to the maximum possible Y
      newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
    }
703

Matthew Woehlke's avatar
Matthew Woehlke committed
704
    // move to the new center
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
705
    m_selRect.moveCenter(newCenter);
706
707
    // update the grab rectangle display
    m_selRect.update();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
708
709
    grabFrame();
  }
Sarang Lakare's avatar
Sarang Lakare committed
710
711
712
713
}

void KMagZoomView::keyPressEvent(QKeyEvent *e)
{
714
  int offset = 16;
715
  if (e->modifiers() & Qt::ShiftModifier)
716
717
    offset = 1;

Laurent Montel's avatar
Laurent Montel committed
718
  if (e->key() == Qt::Key_Control)
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
719
    m_ctrlKeyPressed = true;
Laurent Montel's avatar
Laurent Montel committed
720
  else if (e->key() == Qt::Key_Shift)
Matthew Woehlke's avatar
Matthew Woehlke committed
721
    m_shiftKeyPressed = true;
Laurent Montel's avatar
Laurent Montel committed
722
  else if (e->key() == Qt::Key_Left)
723
  {
724
    if (e->modifiers() & Qt::ControlModifier)
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
    {
      if (offset >= m_selRect.width())
        m_selRect.setWidth (1);
      else
        m_selRect.setWidth (m_selRect.width()-offset);
  }
    else if (contentsX() > 0)
    {
      offset = (int)(offset*m_zoom);
      if (contentsX() > offset)
        setContentsPos (contentsX()-offset, contentsY());
      else
        setContentsPos (0, contentsY());
    }
    else if (m_followMouse == false)
    {
      if (offset > m_selRect.x())
        m_selRect.setX (0);
      else
Laurent Montel's avatar
Laurent Montel committed
744
        m_selRect.translate (-offset,0);
745
746
747
    }
    m_selRect.update();
  }
Laurent Montel's avatar
Laurent Montel committed
748
  else if (e->key() == Qt::Key_Right)
749
  {
750
    if (e->modifiers() & Qt::ControlModifier)
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
    {
      if (m_selRect.right()+offset >= QApplication::desktop()->width())
        m_selRect.setRight (QApplication::desktop()->width()-1);
      else
        m_selRect.setRight (m_selRect.right()+offset);
    }
    else if (contentsX() < contentsWidth()-visibleWidth())
    {
      offset = (int)(offset*m_zoom);
      if (contentsX()+offset < contentsWidth()-visibleWidth())
        setContentsPos (contentsX()+offset, contentsY());
      else
        setContentsPos (contentsWidth()-visibleWidth(), contentsY());
    }
    else if (m_followMouse == false)
    {
      if (m_selRect.right()+offset >= QApplication::desktop()->width())
        m_selRect.moveTopRight (QPoint (QApplication::desktop()->width()-1, m_selRect.top()));
      else
Laurent Montel's avatar
Laurent Montel committed
770
        m_selRect.translate (offset,0);
771
772
773
    }
    m_selRect.update();
  }
Laurent Montel's avatar
Laurent Montel committed
774
  else if (e->key() == Qt::Key_Up)
775
  {
776
    if (e->modifiers() & Qt::ControlModifier)
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
    {
      if (offset >= m_selRect.height())
        m_selRect.setHeight (1);
      else
        m_selRect.setHeight (m_selRect.height()-offset);
    }
    else if (contentsY() > 0)
    {
      offset = (int)(offset*m_zoom);
      if (contentsY() > offset)
        setContentsPos (contentsX(), contentsY()-offset);
      else
        setContentsPos (contentsX(), 0);
    }
    else if (m_followMouse == false)
    {
      if (offset > m_selRect.y())
        m_selRect.setY (0);
      else
Laurent Montel's avatar
Laurent Montel committed
796
        m_selRect.translate (0, -offset);
797
798
    }
    m_selRect.update();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
799
  }
Laurent Montel's avatar
Laurent Montel committed
800
  else if (e->key() == Qt::Key_Down)
801
  {
802
    if (e->modifiers() & Qt::ControlModifier)
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
    {
      if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
        m_selRect.setBottom (QApplication::desktop()->height()-1);
      else
        m_selRect.setBottom (m_selRect.bottom()+offset);
    }
    else if (contentsY() < contentsHeight()-visibleHeight())
    {
      offset = (int)(offset*m_zoom);
      if (contentsY()+offset < contentsHeight()-visibleHeight())
        setContentsPos (contentsX(), contentsY()+offset);
      else
        setContentsPos (contentsX(), contentsHeight()-visibleHeight());
    }
    else if (m_followMouse == false)
    {
      if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
        m_selRect.moveBottomLeft (QPoint (m_selRect.left(), QApplication::desktop()->height()-1));
      else
Laurent Montel's avatar
Laurent Montel committed
822
        m_selRect.translate (0, offset);
823
824
825
826
827
    }
    m_selRect.update();
  }
  else
    e->ignore();
Sarang Lakare's avatar
Sarang Lakare committed
828
829
830
831
}

void KMagZoomView::keyReleaseEvent(QKeyEvent *e)
{
Laurent Montel's avatar
Laurent Montel committed
832
  if (e->key() == Qt::Key_Control)
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
833
    m_ctrlKeyPressed = false;
Laurent Montel's avatar
Laurent Montel committed
834
  else if (e->key() == Qt::Key_Shift)
835
836
    m_shiftKeyPressed = false;
  else
Sarang Lakare's avatar
Sarang Lakare committed
837
838
839
840
841
    e->ignore();
}

void KMagZoomView::focusOutEvent(QFocusEvent *e)
{
842
  if(e->lostFocus() == true) {
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
843
844
845
    m_ctrlKeyPressed = false;
    m_shiftKeyPressed = false;
  }
Sarang Lakare's avatar
Sarang Lakare committed
846
847
848
849
}

// SLOTS

Sarang Lakare's avatar
Sarang Lakare committed
850
851
852
853
854
855
/**
 * This will fit the zoom view to the view window, thus using the maximum
 * possible space in the window.
 */
void KMagZoomView::fitToWindow()
{
856
  unsigned int newWidth, newHeight;
Matthew Woehlke's avatar
Matthew Woehlke committed
857

858
859
860
  // this is a temporary solution, cast, maybe newWidth and newHeight should be float
  if ((m_rotation == 90) || (m_rotation == 270))
  {
861
862
    newWidth = static_cast<unsigned int>((visibleHeight() + m_zoom - 1) / m_zoom);
    newHeight = static_cast<unsigned int>((visibleWidth() + m_zoom - 1) / m_zoom);
863
  } else {
864
865
    newWidth = static_cast<unsigned int>((visibleWidth() + m_zoom - 1) / m_zoom);
    newHeight = static_cast<unsigned int>((visibleHeight() + m_zoom - 1) / m_zoom);
866
  }
Sarang Lakare's avatar
Sarang Lakare committed
867

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
868
  QPoint currCenter = m_selRect.center();
Sarang Lakare's avatar
Sarang Lakare committed
869

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
870
871
  m_selRect.setWidth(newWidth);
  m_selRect.setHeight(newHeight);
Sarang Lakare's avatar
Sarang Lakare committed
872

Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
873
874
875
876
877
878
879
880
   // make sure the selection window does not go outside of the display
   if(currCenter.x() < m_selRect.width()/2) {
     // set X to the minimum possible X
     currCenter.setX(m_selRect.width()/2);
   } else if(currCenter.x() >=  QApplication::desktop()->width()-m_selRect.width()/2) {
     // set X to the maximum possible X
     currCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
   }
Sarang Lakare's avatar
Sarang Lakare committed
881
882

   if(currCenter.y() < m_selRect.height()/2) {
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
883
884
885
886
887
888
889
890
     // set Y to the minimum possible Y
     currCenter.setY(m_selRect.height()/2);
   } else if(currCenter.y() >=  QApplication::desktop()->height()-m_selRect.height()/2) {
     // set Y to the maximum possible Y
     currCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
   }

  m_selRect.moveCenter(currCenter);
Sarang Lakare's avatar
Sarang Lakare committed
891
892
  // update the grab rectangle display
  m_selRect.update();
893
//  m_fitToWindow = true;
894
  viewport()->update();
Sarang Lakare's avatar
Sarang Lakare committed
895
896
}

897
898
899
900
901
902
903
904
void KMagZoomView::setFitToWindow(bool fit)
{
  m_fitToWindow = fit;
  if (fit)
    fitToWindow();
}


905
906
/**
 * Grabs frame from X
Sarang Lakare's avatar
Sarang Lakare committed
907
908
909
 */
void KMagZoomView::grabFrame()
{
910
911
912
913
  // check refresh status
  if (!m_refreshSwitch)
     return;

Sebastian Sauer's avatar
Sebastian Sauer committed
914
  // check if follow-mouse or follow-focus are enabled
915
  if((m_followMouse || m_followFocus) && (m_mouseMode != ResizeSelection)) {
Sebastian Sauer's avatar
Sebastian Sauer committed
916
917
918
919
920
921
    // center-position of the grab-area
    QPoint newCenter;

    if(m_followMouse) {
        // set new center to be the current mouse position
        newCenter = QCursor::pos();
922
#ifdef QAccessibilityClient_FOUND
Sebastian Sauer's avatar
Sebastian Sauer committed
923
924
    } else if(m_followFocus) {
        // set the new center to the current keyboard cursor position
Sebastian Sauer's avatar
Sebastian Sauer committed
925
        newCenter = m_oldFocus;
926
927
928
929
        if(m_followBoth) {
            m_followFocus=false;
            m_followMouse=true;
        }
930
#endif
Sebastian Sauer's avatar
Sebastian Sauer committed
931
    }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948

    // make sure the mouse position is not taking the grab window outside
    // the display
    if(newCenter.x() < m_selRect.width()/2) {
      // set X to the minimum possible X
      newCenter.setX(m_selRect.width()/2);
    } else if(newCenter.x() >=  QApplication::desktop()->width()-m_selRect.width()/2) {
      // set X to the maximum possible X
      newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
    }

    if(newCenter.y() < m_selRect.height()/2) {
      // set Y to the minimum possible Y
      newCenter.setY(m_selRect.height()/2);
    } else if(newCenter.y() >=  QApplication::desktop()->height()-m_selRect.height()/2) {
      // set Y to the maximum possible Y
      newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
949
    }
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
950
951
952
    // move to the new center
    m_selRect.moveCenter(newCenter);

953
954
    // update the grab rectangle display
    m_selRect.update();
Olaf Schmidt-Wischhöfer's avatar
Olaf Schmidt-Wischhöfer committed
955
  }
Sarang Lakare's avatar
Sarang Lakare committed
956
957

  // define a normalized rectangle
Laurent Montel's avatar
Laurent Montel committed
958
  QRect selRect = m_selRect.normalized();
Sarang Lakare's avatar
Sarang Lakare committed
959
960

  // grab screenshot from the screen and put it in the pixmap
961
962
963
  QScreen *screen = qApp->primaryScreen(); // ## How to select the right screen?
  m_coloredPixmap = screen->grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(),
                                      selRect.width(), selRect.height());
Sarang Lakare's avatar
Sarang Lakare committed
964

965
966
967
  // colorize the grabbed pixmap
  if (m_colormode != 0)
    m_coloredPixmap = QPixmap::fromImage(ColorSim::recolor(m_coloredPixmap.toImage(), m_colormode));
968

Christoph Feck's avatar
Christoph Feck committed
969
970
971
972
973
974
975
976
977
  // erase background covered by kmag view ...
  QRect viewRect = rect();
  viewRect.translate(mapTo(window(), QPoint(0, 0)));
  viewRect.translate(-selRect.topLeft());
  viewRect.translate(window()->geometry().topLeft());
  QRegion region(viewRect);

  // ... but exclude own popups ...
  const QList<QWidget *> siblings = QApplication::topLevelWidgets();
978
  for (QWidget *sibling : siblings) {
Christoph Feck's avatar
Christoph Feck committed
979
980
981
982
983
984
985
986
    if (sibling != window() && (sibling->windowType() & Qt::Window) && sibling->isVisible()) {
      QRect rect = sibling->frameGeometry();
      rect.translate(-selRect.topLeft());
      region -= rect;
    }
  }

  QPainter p(&m_coloredPixmap);
987
  for (const QRect &rect : region) {
Christoph Feck's avatar
Christoph Feck committed
988
989
990
991
    p.fillRect(rect, palette().dark());
  }
  p.end();

Christoph Feck's avatar
Christoph Feck committed
992
  QRect r = m_zoomMatrix.mapRect(m_coloredPixmap.rect());
Sarang Lakare's avatar
Sarang Lakare committed
993
  // call repaint to display the newly grabbed image
Christoph Feck's avatar
Christoph Feck committed
994
995
  horizontalScrollBar()->setPageStep(r.width());
  verticalScrollBar()->setPageStep(r.height());
996
  viewport()->update();
Sarang Lakare's avatar
Sarang Lakare committed
997
998
}

999
1000

/**