// SPDX-FileCopyrightText: 2025 KylinSoft Co., Ltd.
//
// SPDX-License-Identifier: GPL-1.0-or-later

#include "xdgpopup.h"
#include "ukuishellsurface.h"
#include "ukuishellsurfacev1.h"

#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <QtWaylandClient/private/qwaylandinputdevice_p.h>

#include <QtGui/private/qwindow_p.h>

#include <QtGui/QGuiApplication>

namespace QtWaylandClient
{

Popup::Popup(UkuiShellSurface *ukuiShellSurface, QWaylandWindow *parent, QtWayland::xdg_positioner *positioner)
    : m_ukuiShellSurface(ukuiShellSurface)
    , m_parentUkuiShellSurface(qobject_cast<UkuiShellSurface *>(parent->shellSurface()))
    , m_parent(parent)
{
    init(ukuiShellSurface->get_popup(m_parentUkuiShellSurface ? m_parentUkuiShellSurface->xdg_surface::object() : nullptr, positioner->object()));
}

Popup::Popup(UkuiShellSurfaceV1 *ukuiShellSurfaceV1, QWaylandWindow *parent, QtWayland::xdg_positioner *positioner)
    : m_ukuiShellSurfaceV1(ukuiShellSurfaceV1)
    , m_parentUkuiShellSurfaceV1(qobject_cast<UkuiShellSurfaceV1 *>(parent->shellSurface()))
    , m_parent(parent)
{
    init(ukuiShellSurfaceV1->get_popup(m_parentUkuiShellSurfaceV1 ? m_parentUkuiShellSurfaceV1->xdg_surface::object() : nullptr, positioner->object()));
}

Popup::~Popup()
{
    if (isInitialized())
        destroy();

    if (m_ukuiShellSurfaceV1) {
        if (m_grabbing) {
            m_grabbing = false;

            // Synthesize Qt enter/leave events for popup
            QWindow *leave = nullptr;
            if (m_ukuiShellSurfaceV1 && m_ukuiShellSurfaceV1->window())
                leave = m_ukuiShellSurfaceV1->window()->window();
            QWindowSystemInterface::handleLeaveEvent(leave);

            if (QWindow *enter = QGuiApplication::topLevelAt(QCursor::pos())) {
                QWaylandWindow *waylandWindow = dynamic_cast<QWaylandWindow *>(enter->handle());
                auto input_device = waylandWindow->display()->defaultInputDevice();
                QWaylandWindow *pointerFocusWindow = nullptr;
                if (input_device)
                    pointerFocusWindow = input_device->pointerFocus();
                if (pointerFocusWindow && pointerFocusWindow == waylandWindow)
                    QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()),    QCursor::pos());
            }
        }
    } else if (m_ukuiShellSurface) {
        if (m_grabbing) {
            m_grabbing = false;

            // Synthesize Qt enter/leave events for popup
            QWindow *leave = nullptr;
            if (m_ukuiShellSurface && m_ukuiShellSurface->window())
                leave = m_ukuiShellSurface->window()->window();
            QWindowSystemInterface::handleLeaveEvent(leave);

            if (QWindow *enter = QGuiApplication::topLevelAt(QCursor::pos()))
                QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()), QCursor::pos());
        }
    }


}

UkuiShellSurface *Popup::ukuiShellSurface()
{
    return m_ukuiShellSurface;
}

UkuiShellSurfaceV1 *Popup::ukuiShellSurfaceV1()
{
    return m_ukuiShellSurfaceV1;
}

void Popup::grab(QWaylandInputDevice *seat, uint serial)
{
    xdg_popup::grab(seat->wl_seat(), serial);
    m_grabbing = true;
}

void Popup::xdg_popup_popup_done()
{
    if (m_ukuiShellSurfaceV1) {
        m_ukuiShellSurfaceV1->window()->window()->close();
    } else if (m_ukuiShellSurface) {
        m_ukuiShellSurface->window()->window()->close();
    }
}

} // namespace QtWaylandClient
