/*

Dialog class that handles input focus in absence of a wm

Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>


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.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

*/

#include "kfdialog.h"
#include "kdmconfig.h"
#include "kdm_greet.h"

#include <KGuiItem>
#include <KPushButton>

#include <QApplication>
#include <QDesktopWidget>
#include <QFrame>
#include <QGridLayout>
#include <QLabel>
#include <QMouseEvent>
#include <QX11Info>

#include <X11/Xlib.h>

#include <stdio.h>

FDialog::FDialog(QWidget *parent, bool framed)
    : inherited(parent/*, framed ? 0 : WStyle_NoBorder*/)
    , readyEmitted(false)
{
    setModal(true);
    if (framed) {
        winFrame = new QFrame(this);
        winFrame->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
        winFrame->setLineWidth(2);
    } else {
        winFrame = 0;
    }
}

void
FDialog::resizeEvent(QResizeEvent *e)
{
    inherited::resizeEvent(e);
    if (winFrame)
        winFrame->resize(size());
}

void
FDialog::paintEvent(QPaintEvent *e)
{
    inherited::paintEvent(e);
    if (!readyEmitted) {
        readyEmitted = true;
        emit ready();
    }
}

void
FDialog::fitInto(const QRect &scr, QRect &grt)
{
    int di;
    if ((di = scr.right() - grt.right()) < 0)
        grt.translate(di, 0);
    if ((di = scr.left() - grt.left()) > 0)
        grt.translate(di, 0);
    if ((di = scr.bottom() - grt.bottom()) < 0)
        grt.translate(0, di);
    if ((di = scr.top() - grt.top()) > 0)
        grt.translate(0, di);
}

void
FDialog::adjustGeometry()
{
    QDesktopWidget *dsk = qApp->desktop();

    QRect scr = dsk->screenGeometry(_greeterScreen);
    if (!winFrame) {
        setGeometry(scr);
    } else {
        setMaximumSize(scr.size() * .9);
        setMinimumSize(0, 0);
        adjustSize();
    }

    if (parentWidget())
        return;

    QRect grt(rect());
    if (winFrame) {
        unsigned x = 50, y = 50;
        sscanf(_greeterPos, "%u,%u", &x, &y);
        grt.moveCenter(QPoint(scr.x() + scr.width() * x / 100,
                              scr.y() + scr.height() * y / 100));
        fitInto(scr, grt);
        setGeometry(grt);
    }

    if (dsk->screenNumber(QCursor::pos()) != _greeterScreen)
        QCursor::setPos(grt.center());
}

static void
fakeFocusIn(WId window)
{
    // We have keyboard grab, so this application will
    // get keyboard events even without having focus.
    // Fake FocusIn to make Qt realize it has the active
    // window, so that it will correctly show cursor in the dialog.
    XEvent ev;
    memset(&ev, 0, sizeof(ev));
    ev.xfocus.display = QX11Info::display();
    ev.xfocus.type = FocusIn;
    ev.xfocus.window = window;
    ev.xfocus.mode = NotifyNormal;
    ev.xfocus.detail = NotifyAncestor;
    XSendEvent(QX11Info::display(), window, False, NoEventMask, &ev);
}

int
FDialog::exec()
{
    static QWidget *current;

    adjustGeometry();
    if (_grabInput && !current)
        secureInputs(QX11Info::display());
    show();
    qApp->processEvents();
    if (_grabInput)
        fakeFocusIn(winId());
    else
        activateWindow();
    QWidget *previous = current;
    current = this;
    inherited::exec();
    current = previous;
    if (current) {
        if (_grabInput)
            fakeFocusIn(current->winId());
        else
            current->activateWindow();
    } else {
        if (_grabInput)
            unsecureInputs(QX11Info::display());
    }
    return result();
}

KFMsgBox::KFMsgBox(QWidget *parent, QMessageBox::Icon type, const QString &text)
    : inherited(parent)
{
    QLabel *label1 = new QLabel(this);
    label1->setPixmap(QMessageBox::standardIcon(type));
    QLabel *label2 = new QLabel(text, this);
    KPushButton *button = new KPushButton(KStandardGuiItem::ok(), this);
    button->setDefault(true);
    button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
    connect(button, SIGNAL(clicked()), SLOT(accept()));

    QGridLayout *grid = new QGridLayout(this);
    grid->addWidget(label1, 0, 0, Qt::AlignCenter);
    grid->addWidget(label2, 0, 1, Qt::AlignCenter);
    grid->addWidget(button, 1, 0, 1, 2, Qt::AlignCenter);
}

void
KFMsgBox::box(QWidget *parent, QMessageBox::Icon type, const QString &text)
{
    KFMsgBox dlg(parent, type, text.trimmed());
    dlg.exec();
}

#include "kfdialog.moc"
