#ifndef ORBITHUB_VNC_DISPLAY_WIDGET_H #define ORBITHUB_VNC_DISPLAY_WIDGET_H #include #include #include class QKeyEvent; class QMouseEvent; class QPaintEvent; class QResizeEvent; class QTimer; class QWheelEvent; // Renders a VNC framebuffer and forwards local input, scaled-to-fit -- // same shape as RdpDisplayWidget, including remote cursor-shape sync. class VncDisplayWidget : public QWidget { Q_OBJECT public: explicit VncDisplayWidget(QWidget* parent = nullptr); void setFrame(const QImage& frame); void setRemoteDesktopSize(int width, int height); void clearFrame(); // true (default): scale the whole remote screen to fit the widget, // like RdpDisplayWidget. false: render at the remote's actual pixel // size -- meant to be placed inside a QScrollArea, whose scrollbars // then let the user pan around a screen larger than the window // instead of shrinking small text to illegibility. VNC has no // equivalent of RDP's MS-RDPEDISP to request a different resolution // from the guest, so this is the only way to see it at native size. void setScaleToFit(bool scaleToFit); bool scaleToFit() const { return m_scaleToFit; } // Mirrors RdpDisplayWidget's cursor handling. VNC's Cursor pseudo- // encoding never signals "reset to default" the way RDP's SetDefault // callback does -- it only ever supplies a shape or hides the cursor -- // so setCursorDefault() exists for symmetry/future use but VNC sessions // never call it today. void setCursorImage(const QImage& image, const QPoint& hotspot); void setCursorHidden(); void setCursorDefault(); signals: void keyInput(int key, quint32 nativeScanCode, const QString& text, bool pressed, int modifiers); void mouseMoveInput(int x, int y); void mouseButtonInput(int x, int y, int button, bool pressed); void mouseWheelInput(int x, int y, int deltaX, int deltaY); void viewportSizeChanged(int width, int height); void displayScaleChanged(qreal devicePixelRatio); protected: void paintEvent(QPaintEvent* event) override; void resizeEvent(QResizeEvent* event) override; bool event(QEvent* event) override; void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void wheelEvent(QWheelEvent* event) override; bool focusNextPrevChild(bool next) override; private: enum class CursorMode { Default, Hidden, Custom, }; QImage m_frame; QSize m_remoteSize; QTimer* m_resizeDebounceTimer; bool m_scaleToFit; QImage m_cursorImage; QPoint m_cursorHotspot; CursorMode m_cursorMode; QRectF renderRect() const; QPoint mapToRemote(const QPointF& pos) const; QSize effectiveRemoteSize() const; void emitViewportGeometry(); void scheduleViewportGeometryEmit(); void applySizeConstraint(); void applyCursor(); }; #endif