From 8f9369beebf60f3b10d75f50507b194f2ccdaceb Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Thu, 21 May 2020 18:43:07 +0200
Subject: add screen layout system

---
 src/frontend/Util_Video.cpp | 334 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 334 insertions(+)
 create mode 100644 src/frontend/Util_Video.cpp

(limited to 'src/frontend/Util_Video.cpp')

diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp
new file mode 100644
index 0000000..cd4e21c
--- /dev/null
+++ b/src/frontend/Util_Video.cpp
@@ -0,0 +1,334 @@
+/*
+    Copyright 2016-2020 Arisotura
+
+    This file is part of melonDS.
+
+    melonDS 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 3 of the License, or (at your option)
+    any later version.
+
+    melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cmath>
+#include <algorithm>
+
+#include "FrontendUtil.h"
+
+
+namespace Frontend
+{
+
+float TopScreenMtx[6];
+float BotScreenMtx[6];
+float TouchMtx[6];
+
+
+void M23_Identity(float* m)
+{
+    m[0] = 1; m[1] = 0;
+    m[2] = 0; m[3] = 1;
+    m[4] = 0; m[5] = 0;
+}
+
+void M23_Scale(float* m, float s)
+{
+    m[0] *= s; m[1] *= s;
+    m[2] *= s; m[3] *= s;
+    m[4] *= s; m[5] *= s;
+}
+
+void M23_RotateFast(float* m, int angle)
+{
+    if (angle == 0) return;
+
+    float temp[4]; memcpy(temp, m, sizeof(float)*4);
+
+    switch (angle)
+    {
+    case 1: // 90
+        m[0] = temp[2];
+        m[1] = temp[3];
+        m[2] = -temp[0];
+        m[3] = -temp[1];
+        break;
+
+    case 2: // 180
+        m[0] = -temp[0];
+        m[1] = -temp[1];
+        m[2] = -temp[2];
+        m[3] = -temp[3];
+        break;
+
+    case 3: // 270
+        m[0] = -temp[2];
+        m[1] = -temp[3];
+        m[2] = temp[0];
+        m[3] = temp[1];
+        break;
+    }
+}
+
+void M23_Translate(float* m, float tx, float ty)
+{
+    m[4] += tx;
+    m[5] += ty;
+}
+
+void M23_Multiply(float* m, float* _a, float* _b)
+{
+    float a[6]; memcpy(a, _a, 6*sizeof(float));
+    float b[6]; memcpy(b, _b, 6*sizeof(float));
+
+    m[0] = (a[0] * b[0]) + (a[2] * b[1]);
+    m[1] = (a[1] * b[0]) + (a[3] * b[1]);
+
+    m[2] = (a[0] * b[2]) + (a[2] * b[3]);
+    m[3] = (a[1] * b[2]) + (a[3] * b[3]);
+
+    m[4] = (a[0] * b[4]) + (a[2] * b[5]) + a[4];
+    m[5] = (a[1] * b[4]) + (a[3] * b[5]) + a[5];
+}
+
+void M23_Transform(float* m, float& x, float& y)
+{
+    float vx = x;
+    float vy = y;
+
+    x = (vx * m[0]) + (vy * m[2]) + m[4];
+    y = (vx * m[1]) + (vy * m[3]) + m[5];
+}
+
+
+void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale)
+{
+    float refpoints[4][2] =
+    {
+        {0, 0}, {256, 192},
+        {0, 0}, {256, 192}
+    };
+
+    int layout = screenLayout == 0
+        ? ((rotation % 2 == 0) ? 0 : 1)
+        : screenLayout - 1;
+
+    float botScale = 1;
+    float botTrans[4] = {0};
+
+    M23_Identity(TopScreenMtx);
+    M23_Identity(BotScreenMtx);
+
+    M23_Translate(TopScreenMtx, -256/2, -192/2);
+    M23_Translate(BotScreenMtx, -256/2, -192/2);
+
+    // rotation
+    {
+        float rotmtx[6];
+        M23_Identity(rotmtx);
+
+        M23_RotateFast(rotmtx, rotation);
+        M23_Multiply(TopScreenMtx, rotmtx, TopScreenMtx);
+        M23_Multiply(BotScreenMtx, rotmtx, BotScreenMtx);
+
+        M23_Transform(TopScreenMtx, refpoints[0][0], refpoints[0][1]);
+        M23_Transform(TopScreenMtx, refpoints[1][0], refpoints[1][1]);
+        M23_Transform(BotScreenMtx, refpoints[2][0], refpoints[2][1]);
+        M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]);
+    }
+
+    // move screens apart
+    {
+        int idx = layout == 0 ? 1 : 0;
+        float offset =
+            (((layout == 0 && (rotation % 2 == 0)) || (layout == 1 && (rotation % 2 == 1))
+                ? 192.f : 256.f)
+            + screenGap) / 2.f;
+        if (rotation == 1 || rotation == 2)
+            offset *= -1.f;
+
+        M23_Translate(TopScreenMtx, (idx==0)?-offset:0, (idx==1)?-offset:0);
+        M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0);
+
+        refpoints[0][idx] -= offset;
+        refpoints[1][idx] -= offset;
+        refpoints[2][idx] += offset;
+        refpoints[3][idx] += offset;
+
+        botTrans[idx] = offset;
+    }
+
+    // scale
+    {
+        if (sizing == 0)
+        {
+            float minX = refpoints[0][0], maxX = minX;
+            float minY = refpoints[0][1], maxY = minY;
+
+            for (int i = 1; i < 4; i++)
+            {
+                minX = std::min(minX, refpoints[i][0]);
+                minY = std::min(minY, refpoints[i][1]);
+                maxX = std::max(maxX, refpoints[i][0]);
+                maxY = std::max(maxY, refpoints[i][1]);
+            }
+
+            float hSize = maxX - minX;
+            float vSize = maxY - minY;
+
+            // scale evenly
+            float scale = std::min(screenWidth / hSize, screenHeight / vSize);
+
+            if (integerScale)
+                scale = floor(scale);
+
+            M23_Scale(TopScreenMtx, scale);
+            M23_Scale(BotScreenMtx, scale);
+
+            for (int i = 0; i < 4; i++)
+            {
+                refpoints[i][0] *= scale;
+                refpoints[i][1] *= scale;
+            }
+
+            botScale = scale;
+        }
+        else
+        {
+            int primOffset = (sizing == 1) ? 0 : 2;
+            int secOffset = (sizing == 1) ? 2 : 0;
+            float* primMtx = (sizing == 1) ? TopScreenMtx : BotScreenMtx;
+            float* secMtx = (sizing == 1) ? BotScreenMtx : TopScreenMtx;
+
+            float primMinX = refpoints[primOffset][0], primMaxX = primMinX;
+            float primMinY = refpoints[primOffset][1], primMaxY = primMinY;
+            float secMinX = refpoints[secOffset][0], secMaxX = secMinX;
+            float secMinY = refpoints[secOffset][1], secMaxY = secMinY;
+
+            primMinX = std::min(primMinX, refpoints[primOffset+1][0]);
+            primMinY = std::min(primMinY, refpoints[primOffset+1][1]);
+            primMaxX = std::max(primMaxX, refpoints[primOffset+1][0]);
+            primMaxY = std::max(primMaxY, refpoints[primOffset+1][1]);
+
+            secMinX = std::min(secMinX, refpoints[secOffset+1][0]);
+            secMinY = std::min(secMinY, refpoints[secOffset+1][1]);
+            secMaxX = std::max(secMaxX, refpoints[secOffset+1][0]);
+            secMaxY = std::max(secMaxY, refpoints[secOffset+1][1]);
+
+            float primHSize = layout == 1 ? std::max(primMaxX, -primMinX) : primMaxX - primMinX;
+            float primVSize = layout == 0 ? std::max(primMaxY, -primMinY) : primMaxY - primMinY;
+
+            float secHSize = layout == 1 ? std::max(secMaxX, -secMinX) : secMaxX - secMinX;
+            float secVSize = layout == 0 ? std::max(secMaxY, -secMinY) : secMaxY - secMinY;
+
+            float primScale = std::min(screenWidth / primHSize, screenHeight / primVSize);
+            float secScale = 1.f;
+
+            if (layout == 0)
+            {
+                if (screenHeight - primVSize * primScale < secVSize)
+                    primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize);
+                else
+                    secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
+            }
+            else
+            {
+                if (screenWidth - primHSize * primScale < secHSize)
+                    primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize);
+                else
+                    secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
+            }
+
+            if (integerScale)
+            {
+                primScale = floor(primScale);
+                secScale = floor(secScale);
+            }
+
+            M23_Scale(primMtx, primScale);
+            M23_Scale(secMtx, secScale);
+
+            refpoints[primOffset+0][0] *= primScale;
+            refpoints[primOffset+0][1] *= primScale;
+            refpoints[primOffset+1][0] *= primScale;
+            refpoints[primOffset+1][1] *= primScale;
+            refpoints[secOffset+0][0] *= secScale;
+            refpoints[secOffset+0][1] *= secScale;
+            refpoints[secOffset+1][0] *= secScale;
+            refpoints[secOffset+1][1] *= secScale;
+
+            botScale = (sizing == 1) ? secScale : primScale;
+        }
+    }
+
+    // position
+    {
+        float minX = refpoints[0][0], maxX = minX;
+        float minY = refpoints[0][1], maxY = minY;
+
+        for (int i = 1; i < 4; i++)
+        {
+            minX = std::min(minX, refpoints[i][0]);
+            minY = std::min(minY, refpoints[i][1]);
+            maxX = std::max(maxX, refpoints[i][0]);
+            maxY = std::max(maxY, refpoints[i][1]);
+        }
+
+        float width = maxX - minX;
+        float height = maxY - minY;
+
+        float tx = (screenWidth/2) - (width/2) - minX;
+        float ty = (screenHeight/2) - (height/2) - minY;
+
+        M23_Translate(TopScreenMtx, tx, ty);
+        M23_Translate(BotScreenMtx, tx, ty);
+
+        botTrans[2] = tx; botTrans[3] = ty;
+    }
+
+    // prepare a 'reverse' matrix for the touchscreen
+    // this matrix undoes the transforms applied to the bottom screen
+    // and can be used to calculate touchscreen coords from host screen coords
+    {
+        M23_Identity(TouchMtx);
+
+        M23_Translate(TouchMtx, -botTrans[2], -botTrans[3]);
+        M23_Scale(TouchMtx, 1.f / botScale);
+        M23_Translate(TouchMtx, -botTrans[0], -botTrans[1]);
+
+        float rotmtx[6];
+        M23_Identity(rotmtx);
+        M23_RotateFast(rotmtx, (4-rotation) & 3);
+        M23_Multiply(TouchMtx, rotmtx, TouchMtx);
+
+        M23_Translate(TouchMtx, 256/2, 192/2);
+    }
+}
+
+float* GetScreenTransform(int screen)
+{
+    if (screen == 0) return TopScreenMtx;
+    else             return BotScreenMtx;
+}
+
+void GetTouchCoords(int& x, int& y)
+{
+    float vx = x;
+    float vy = y;
+
+    M23_Transform(TouchMtx, vx, vy);
+
+    x = (int)vx;
+    y = (int)vy;
+}
+
+}
+
-- 
cgit v1.2.3


From ffd9c61bf79852f2364166c4770719146500f4b9 Mon Sep 17 00:00:00 2001
From: RSDuck <rsduck@users.noreply.github.com>
Date: Thu, 21 May 2020 19:45:33 +0200
Subject: fix screen layout with emphasis

---
 src/frontend/Util_Video.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/frontend/Util_Video.cpp')

diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp
index cd4e21c..0f5ff66 100644
--- a/src/frontend/Util_Video.cpp
+++ b/src/frontend/Util_Video.cpp
@@ -235,14 +235,14 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
             if (layout == 0)
             {
                 if (screenHeight - primVSize * primScale < secVSize)
-                    primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize);
+                    primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
                 else
                     secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
             }
             else
             {
                 if (screenWidth - primHSize * primScale < secHSize)
-                    primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize);
+                    primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
                 else
                     secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
             }
-- 
cgit v1.2.3


From 16252a85e70feaa1bd10312a357ac74bd677ade3 Mon Sep 17 00:00:00 2001
From: Arisotura <thetotalworm@gmail.com>
Date: Sun, 24 May 2020 23:16:56 +0200
Subject: separate screen handling shit to a specialized class

---
 src/frontend/FrontendUtil.h  |   5 +-
 src/frontend/Util_Video.cpp  |   6 +-
 src/frontend/qt_sdl/main.cpp | 168 +++++++++++++++++++++++++------------------
 src/frontend/qt_sdl/main.h   |  22 +++++-
 4 files changed, 122 insertions(+), 79 deletions(-)

(limited to 'src/frontend/Util_Video.cpp')

diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h
index 1fd7329..359018f 100644
--- a/src/frontend/FrontendUtil.h
+++ b/src/frontend/FrontendUtil.h
@@ -104,11 +104,12 @@ void UndoStateLoad();
 // * integerScale: force screens to be scaled up at integer scaling factors
 void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale);
 
-// get a 2x3 transform matrix for the given screen (0=top, 1=bottom)
+// get a 2x3 transform matrix for each screen
 // note: the transform assumes an origin point at the top left of the display,
 // X going left and Y going down
 // for each screen the source coordinates should be (0,0) and (256,192)
-float* GetScreenTransform(int screen);
+// 'top' and 'bot' should point each to an array of 6 floats
+void GetScreenTransforms(float* top, float* bot);
 
 // de-transform the provided host display coordinates to get coordinates
 // on the bottom screen
diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp
index 0f5ff66..87cb9b5 100644
--- a/src/frontend/Util_Video.cpp
+++ b/src/frontend/Util_Video.cpp
@@ -313,10 +313,10 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
     }
 }
 
-float* GetScreenTransform(int screen)
+void GetScreenTransforms(float* top, float* bot)
 {
-    if (screen == 0) return TopScreenMtx;
-    else             return BotScreenMtx;
+    memcpy(top, TopScreenMtx, 6*sizeof(float));
+    memcpy(bot, BotScreenMtx, 6*sizeof(float));
 }
 
 void GetTouchCoords(int& x, int& y)
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index 922206f..0e0a21b 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -543,24 +543,22 @@ bool EmuThread::emuIsRunning()
 }
 
 
-MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent)
+void ScreenHandler::screenSetupLayout(int w, int h)
 {
-    screen[0] = new QImage(256, 192, QImage::Format_RGB32);
-    screen[1] = new QImage(256, 192, QImage::Format_RGB32);
-
-    screenTrans[0].reset();
-    screenTrans[1].reset();
+    int sizing = Config::ScreenSizing;
+    if (sizing == 3) sizing = autoScreenSizing;
 
-    touching = false;
-}
+    Frontend::SetupScreenLayout(w, h,
+                                Config::ScreenLayout,
+                                Config::ScreenRotation,
+                                sizing,
+                                Config::ScreenGap,
+                                Config::IntegerScaling != 0);
 
-MainWindowPanel::~MainWindowPanel()
-{
-    delete screen[0];
-    delete screen[1];
+    Frontend::GetScreenTransforms(screenMatrix[0], screenMatrix[1]);
 }
 
-void MainWindowPanel::ensureProperMinSize()
+QSize ScreenHandler::screenGetMinSize()
 {
     bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3);
     int gap = Config::ScreenGap;
@@ -571,48 +569,110 @@ void MainWindowPanel::ensureProperMinSize()
     if (Config::ScreenLayout == 0) // natural
     {
         if (isHori)
-            setMinimumSize(h+gap+h, w);
+            return QSize(h+gap+h, w);
         else
-            setMinimumSize(w, h+gap+h);
+            return QSize(w, h+gap+h);
     }
     else if (Config::ScreenLayout == 1) // vertical
     {
         if (isHori)
-            setMinimumSize(h, w+gap+w);
+            return QSize(h, w+gap+w);
         else
-            setMinimumSize(w, h+gap+h);
+            return QSize(w, h+gap+h);
     }
     else // horizontal
     {
         if (isHori)
-            setMinimumSize(h+gap+h, w);
+            return QSize(h+gap+h, w);
         else
-            setMinimumSize(w+gap+w, h);
+            return QSize(w+gap+w, h);
+    }
+}
+
+void ScreenHandler::screenOnMousePress(QMouseEvent* event)
+{
+    event->accept();
+    if (event->button() != Qt::LeftButton) return;
+
+    int x = event->pos().x();
+    int y = event->pos().y();
+
+    Frontend::GetTouchCoords(x, y);
+
+    if (x >= 0 && x < 256 && y >= 0 && y < 192)
+    {
+        touching = true;
+        NDS::TouchScreen(x, y);
+    }
+}
+
+void ScreenHandler::screenOnMouseRelease(QMouseEvent* event)
+{
+    event->accept();
+    if (event->button() != Qt::LeftButton) return;
+
+    if (touching)
+    {
+        touching = false;
+        NDS::ReleaseScreen();
     }
 }
 
+void ScreenHandler::screenOnMouseMove(QMouseEvent* event)
+{
+    event->accept();
+    if (!(event->buttons() & Qt::LeftButton)) return;
+    if (!touching) return;
+
+    int x = event->pos().x();
+    int y = event->pos().y();
+
+    Frontend::GetTouchCoords(x, y);
+
+    // clamp to screen range
+    if (x < 0) x = 0;
+    else if (x > 255) x = 255;
+    if (y < 0) y = 0;
+    else if (y > 191) y = 191;
+
+    NDS::TouchScreen(x, y);
+}
+
+
+MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent)
+{
+    screen[0] = QImage(256, 192, QImage::Format_RGB32);
+    screen[1] = QImage(256, 192, QImage::Format_RGB32);
+
+    screenTrans[0].reset();
+    screenTrans[1].reset();
+
+    touching = false;
+}
+
+MainWindowPanel::~MainWindowPanel()
+{
+}
+
+void MainWindowPanel::ensureProperMinSize()
+{
+    setMinimumSize(screenGetMinSize());
+}
+
 void MainWindowPanel::setupScreenLayout()
 {
     int w = width();
     int h = height();
     float* mtx;
 
-    int sizing = Config::ScreenSizing;
-    if (sizing == 3) sizing = autoScreenSizing;
-
-    Frontend::SetupScreenLayout(w, h,
-                                Config::ScreenLayout,
-                                Config::ScreenRotation,
-                                sizing,
-                                Config::ScreenGap,
-                                Config::IntegerScaling != 0);
+    screenSetupLayout(w, h);
 
-    mtx = Frontend::GetScreenTransform(0);
+    mtx = screenMatrix[0];
     screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f,
                              mtx[2], mtx[3], 0.f,
                              mtx[4], mtx[5], 1.f);
 
-    mtx = Frontend::GetScreenTransform(1);
+    mtx = screenMatrix[1];
     screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f,
                              mtx[2], mtx[3], 0.f,
                              mtx[4], mtx[5], 1.f);
@@ -628,18 +688,18 @@ void MainWindowPanel::paintEvent(QPaintEvent* event)
     int frontbuf = GPU::FrontBuffer;
     if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return;
 
-    memcpy(screen[0]->scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4);
-    memcpy(screen[1]->scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4);
+    memcpy(screen[0].scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4);
+    memcpy(screen[1].scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4);
 
     painter.setRenderHint(QPainter::SmoothPixmapTransform, Config::ScreenFilter!=0);
 
     QRect screenrc(0, 0, 256, 192);
 
     painter.setTransform(screenTrans[0]);
-    painter.drawImage(screenrc, *screen[0]);
+    painter.drawImage(screenrc, screen[0]);
 
     painter.setTransform(screenTrans[1]);
-    painter.drawImage(screenrc, *screen[1]);
+    painter.drawImage(screenrc, screen[1]);
 }
 
 void MainWindowPanel::resizeEvent(QResizeEvent* event)
@@ -649,51 +709,17 @@ void MainWindowPanel::resizeEvent(QResizeEvent* event)
 
 void MainWindowPanel::mousePressEvent(QMouseEvent* event)
 {
-    event->accept();
-    if (event->button() != Qt::LeftButton) return;
-
-    int x = event->pos().x();
-    int y = event->pos().y();
-
-    Frontend::GetTouchCoords(x, y);
-
-    if (x >= 0 && x < 256 && y >= 0 && y < 192)
-    {
-        touching = true;
-        NDS::TouchScreen(x, y);
-    }
+    screenOnMousePress(event);
 }
 
 void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event)
 {
-    event->accept();
-    if (event->button() != Qt::LeftButton) return;
-
-    if (touching)
-    {
-        touching = false;
-        NDS::ReleaseScreen();
-    }
+    screenOnMouseRelease(event);
 }
 
 void MainWindowPanel::mouseMoveEvent(QMouseEvent* event)
 {
-    event->accept();
-    if (!(event->buttons() & Qt::LeftButton)) return;
-    if (!touching) return;
-
-    int x = event->pos().x();
-    int y = event->pos().y();
-
-    Frontend::GetTouchCoords(x, y);
-
-    // clamp to screen range
-    if (x < 0) x = 0;
-    else if (x > 255) x = 255;
-    if (y < 0) y = 0;
-    else if (y > 191) y = 191;
-
-    NDS::TouchScreen(x, y);
+    screenOnMouseMove(event);
 }
 
 void MainWindowPanel::onScreenLayoutChanged()
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index c0dc465..1121da1 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -64,7 +64,24 @@ private:
 };
 
 
-class MainWindowPanel : public QWidget
+class ScreenHandler
+{
+protected:
+    void screenSetupLayout(int w, int h);
+
+    QSize screenGetMinSize();
+
+    void screenOnMousePress(QMouseEvent* event);
+    void screenOnMouseRelease(QMouseEvent* event);
+    void screenOnMouseMove(QMouseEvent* event);
+
+    float screenMatrix[2][6];
+
+    bool touching;
+};
+
+
+class MainWindowPanel : public QWidget, public ScreenHandler
 {
     Q_OBJECT
 
@@ -88,9 +105,8 @@ private slots:
     void onScreenLayoutChanged();
 
 private:
-    QImage* screen[2];
+    QImage screen[2];
     QTransform screenTrans[2];
-    bool touching;
 };
 
 
-- 
cgit v1.2.3