/**
 * Copyright (C) 2002-2003 by Koos Vriezen <koos.vriezen@gmail.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License version 2 as published by the Free Software Foundation.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 **/

#include <stdio.h>
#include <math.h>

#include <config.h>
// include files for TQt
#include <tqstyle.h>
#include <tqtimer.h>
#include <tqpainter.h>
#include <tqmetaobject.h>
#include <tqlayout.h>
#include <tqpixmap.h>
#include <tqtextedit.h>
#include <tqtooltip.h>
#include <tqapplication.h>
#include <tqiconset.h>
#include <tqcursor.h>
#include <tqkeysequence.h>
#include <tqslider.h>
#include <tqlabel.h>
#include <tqdatastream.h>
#include <tqwidgetstack.h>
#include <tqcursor.h>
#include <tqclipboard.h>

#include <kiconloader.h>
#include <kstatusbar.h>
#include <kdebug.h>
#include <klocale.h>
#include <kapplication.h>
#include <tdeactioncollection.h>
#include <kstdaction.h>
#include <tdeshortcut.h>
#include <kurldrag.h>
#include <kfinddialog.h>
#include <dcopclient.h>
#include <kglobalsettings.h>
#include <kstaticdeleter.h>

#include "kmplayerview.h"
#include "kmplayercontrolpanel.h"
#include "kmplayersource.h"
#include "playlistview.h"
#include "viewarea.h"

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
static const int XKeyPress = KeyPress;
#undef KeyPress
#undef Always
#undef Never
#undef Status
#undef Unsorted
#undef Bool

extern const char * normal_window_xpm[];
extern const char * playlist_xpm[];


/* mouse invisible: define the time (in 1/1000 seconds) before mouse goes invisible */


using namespace KMPlayer;

//-------------------------------------------------------------------------

namespace KMPlayer {

class KMPlayerPictureWidget : public TQWidget {
    View * m_view;
public:
    KDE_NO_CDTOR_EXPORT KMPlayerPictureWidget (TQWidget * parent, View * view)
        : TQWidget (parent), m_view (view) {}
    KDE_NO_CDTOR_EXPORT ~KMPlayerPictureWidget () {}
protected:
    void mousePressEvent (TQMouseEvent *);
};

} // namespace

KDE_NO_EXPORT void KMPlayerPictureWidget::mousePressEvent (TQMouseEvent *) {
    m_view->emitPictureClicked ();
}

//-----------------------------------------------------------------------------

KDE_NO_CDTOR_EXPORT TextEdit::TextEdit (TQWidget * parent, View * view) : TQTextEdit (parent, "kde_kmplayer_console"), m_view (view) {
    setReadOnly (true);
    setPaper (TQBrush (TQColor (0, 0, 0)));
    setColor (TQColor (0xB2, 0xB2, 0xB2));
}

KDE_NO_EXPORT void TextEdit::contextMenuEvent (TQContextMenuEvent * e) {
    m_view->controlPanel ()->popupMenu ()->exec (e->globalPos ());
}

//-----------------------------------------------------------------------------

KDE_NO_CDTOR_EXPORT InfoWindow::InfoWindow (TQWidget * parent, View * view) : TQTextEdit (parent, "kde_kmplayer_console"), m_view (view) {
    setReadOnly (true);
    setLinkUnderline (false);
}

KDE_NO_EXPORT void InfoWindow::contextMenuEvent (TQContextMenuEvent * e) {
    m_view->controlPanel ()->popupMenu ()->exec (e->globalPos ());
}

//-----------------------------------------------------------------------------

KDE_NO_CDTOR_EXPORT View::View (TQWidget *parent, const char *name)
  : KMediaPlayer::View (parent, name),
    m_image (0L),
    m_control_panel (0L),
    m_status_bar (0L),
    m_volume_slider (0L),
    m_mixer_object ("kicker"),
    m_controlpanel_mode (CP_Show),
    m_old_controlpanel_mode (CP_Show),
    m_statusbar_mode (SB_Hide),
    controlbar_timer (0),
    infopanel_timer (0),
    m_keepsizeratio (false),
    m_playing (false),
    m_mixer_init (false),
    m_inVolumeUpdate (false),
    m_tmplog_needs_eol (false),
    m_revert_fullscreen (false),
    m_no_info (false),
    m_edit_mode (false)
{}

KDE_NO_EXPORT void View::dropEvent (TQDropEvent * de) {
    KURL::List sl;
    if (KURLDrag::canDecode (de)) {
        KURLDrag::decode (de, sl);
    } else if (TQTextDrag::canDecode (de)) {
        TQString text;
        TQTextDrag::decode (de, text);
        sl.push_back (KURL (text));
    }
    if (sl.size () > 0) {
        for (unsigned i = 0; i < sl.size (); i++)
            sl [i] = KURL::decode_string (sl [i].url ());
        m_widgetstack->visibleWidget ()->setFocus ();
        emit urlDropped (sl);
        de->accept ();
    }
}

KDE_NO_EXPORT void View::dragEnterEvent (TQDragEnterEvent* dee) {
    if (isDragValid (dee))
        dee->accept ();
}

KDE_NO_EXPORT void View::init (TDEActionCollection * action_collection) {
    setBackgroundMode(TQt::NoBackground); // prevents flashing
    //m_dockarea->setEraseColor (TQColor (0, 0, 0));
    TQPalette pal (TQColor (64, 64,64), TQColor (32, 32, 32));
    TQVBoxLayout * viewbox = new TQVBoxLayout (this, 0, 0);
    m_dockarea = new KDockArea (this, "kde_kmplayer_dock_area");
    m_dock_video = new KDockWidget (m_dockarea->manager (), 0, TDEGlobal::iconLoader ()->loadIcon (TQString ("kmplayer"), TDEIcon::Small), m_dockarea);
    m_dock_video->setEraseColor (TQColor (0, 0, 255));
    m_dock_video->setDockSite (KDockWidget::DockLeft | KDockWidget::DockBottom | KDockWidget::DockRight | KDockWidget::DockTop);
    m_dock_video->setEnableDocking(KDockWidget::DockNone);
    m_view_area = new ViewArea (m_dock_video, this);
    m_dock_video->setWidget (m_view_area);
    m_dockarea->setMainDockWidget (m_dock_video);
    m_dock_playlist = m_dockarea->createDockWidget (i18n ("Play List"), TDEGlobal::iconLoader ()->loadIcon (TQString ("player_playlist"), TDEIcon::Small));
    m_playlist = new PlayListView (m_dock_playlist, this, action_collection);
    m_dock_playlist->setWidget (m_playlist);
    viewbox->addWidget (m_dockarea);
    m_widgetstack = new TQWidgetStack (m_view_area);
    m_control_panel = new ControlPanel (m_view_area, this);
    m_control_panel->setMaximumSize (2500, controlPanel ()->maximumSize ().height ());
    m_status_bar = new StatusBar (m_view_area);
    m_status_bar->insertItem (TQString (""), 0);
    TQSize sbsize = m_status_bar->sizeHint ();
    m_status_bar->hide ();
    m_status_bar->setMaximumSize (2500, sbsize.height ());
    m_viewer = new Viewer (m_widgetstack, this);
    m_widgettypes [WT_Video] = m_viewer;
#if KDE_IS_VERSION(3,1,90)
    setVideoWidget (m_view_area);
#endif

    m_multiedit = new TextEdit (m_widgetstack, this);
    m_multiedit->setTextFormat (TQt::PlainText);
    TQFont fnt = TDEGlobalSettings::fixedFont ();
    m_multiedit->setFont (fnt);
    m_widgettypes[WT_Console] = m_multiedit;

    m_widgettypes[WT_Picture] = new KMPlayerPictureWidget (m_widgetstack, this);

    m_dock_infopanel = m_dockarea->createDockWidget ("infopanel", TDEGlobal::iconLoader ()->loadIcon (TQString ("info"), TDEIcon::Small));
    m_infopanel = new InfoWindow (m_dock_infopanel, this);
    m_dock_infopanel->setWidget (m_infopanel);

    m_widgetstack->addWidget (m_viewer);
    m_widgetstack->addWidget (m_multiedit);
    m_widgetstack->addWidget (m_widgettypes[WT_Picture]);

    setFocusPolicy (TQ_ClickFocus);

    setAcceptDrops (true);
    m_view_area->resizeEvent (0L);

    kapp->installX11EventFilter (this);
}

KDE_NO_CDTOR_EXPORT View::~View () {
    delete m_image;
    if (TQT_BASE_OBJECT(m_view_area->parent ()) != TQT_BASE_OBJECT(this))
        delete m_view_area;
}

KDE_NO_EXPORT void View::setEraseColor (const TQColor & color) {
    KMediaPlayer::View::setEraseColor (color);
    if (statusBar ()) {
        statusBar ()->setEraseColor (color);
        controlPanel ()->setEraseColor (color);
    }
}

void View::setInfoMessage (const TQString & msg) {
    bool ismain = m_dockarea->getMainDockWidget () == m_dock_infopanel;
    if (msg.isEmpty ()) {
        if (!ismain && !m_edit_mode && !infopanel_timer)
            infopanel_timer = startTimer (0);
       m_infopanel->clear ();
    } else if (ismain || !m_no_info) {
        if (!m_edit_mode && m_dock_infopanel->mayBeShow ())
          m_dock_infopanel->manualDock(m_dock_video,KDockWidget::DockBottom,80);
        m_infopanel->setText (msg);
    }
}

void View::setStatusMessage (const TQString & msg) {
    if (m_statusbar_mode != SB_Hide)
        m_status_bar->changeItem (msg, 0);
}

void View::toggleShowPlaylist () {
    if (m_controlpanel_mode == CP_Only)
        return;
    if (m_dock_playlist->mayBeShow ()) {
        if (m_dock_playlist->isDockBackPossible ())
            m_dock_playlist->dockBack ();
        else {
            bool horz = true;
            TQStyle & style = m_playlist->style ();
            int h = style.pixelMetric (TQStyle::PM_ScrollBarExtent, m_playlist);
            h += style.pixelMetric(TQStyle::PM_DockWindowFrameWidth, m_playlist);
            h +=style.pixelMetric(TQStyle::PM_DockWindowHandleExtent,m_playlist);
            for (TQListViewItem *i=m_playlist->firstChild();i;i=i->itemBelow()) {
                h += i->height ();
                if (h > int (0.25 * height ())) {
                    horz = false;
                    break;
                }
            }
            int perc = 30;
            if (horz && 100 * h / height () < perc)
                perc = 100 * h / height ();
            m_dock_playlist->manualDock (m_dock_video, horz ? KDockWidget::DockTop : KDockWidget::DockLeft, perc);
        }
    } else
        m_dock_playlist->undock ();
}

void View::setViewOnly () {
    if (m_dock_playlist->mayBeHide ())
        m_dock_playlist->undock ();
    if (m_dock_infopanel->mayBeHide ())
       m_dock_infopanel->undock ();
}

void View::setInfoPanelOnly () {
    if (m_dock_playlist->mayBeHide ())
        m_dock_playlist->undock ();
    m_dock_video->setEnableDocking (KDockWidget::DockCenter);
    m_dock_video->undock ();
    m_dock_infopanel->setEnableDocking (KDockWidget::DockNone);
    m_dockarea->setMainDockWidget (m_dock_infopanel);
}

void View::setPlaylistOnly () {
    if (m_dock_infopanel->mayBeHide ())
       m_dock_infopanel->undock ();
    m_dock_video->setEnableDocking (KDockWidget::DockCenter);
    m_dock_video->undock ();
    m_dock_playlist->setEnableDocking (KDockWidget::DockNone);
    m_dockarea->setMainDockWidget (m_dock_playlist);
}

void View::setEditMode (RootPlayListItem *ri, bool enable) {
    m_edit_mode = enable;
    m_infopanel->setReadOnly (!m_edit_mode);
    m_infopanel->setTextFormat (enable ? TQt::PlainText : TQt::AutoText);
    if (m_edit_mode && m_dock_infopanel->mayBeShow ())
        m_dock_infopanel->manualDock(m_dock_video,KDockWidget::DockBottom,50);
    m_playlist->showAllNodes (ri, m_edit_mode);
}

bool View::setPicture (const TQString & path) {
    delete m_image;
    if (path.isEmpty ())
        m_image = 0L;
    else {
        m_image = new TQPixmap (path);
        if (m_image->isNull ()) {
            delete m_image;
            m_image = 0L;
            kdDebug() << "View::setPicture failed " << path << endl;
        }
    }
    if (!m_image) {
        m_widgetstack->raiseWidget (m_viewer);
    } else {
        m_widgettypes[WT_Picture]->setPaletteBackgroundPixmap (*m_image);
        m_widgetstack->raiseWidget (m_widgettypes[WT_Picture]);
        setControlPanelMode (CP_AutoHide);
    }
    return m_image;
}

KDE_NO_EXPORT void View::updateVolume () {
    if (m_mixer_init && !m_volume_slider)
        return;
    TQByteArray data, replydata;
    TQCString replyType;
    int volume;
    bool has_mixer = kapp->dcopClient ()->call (m_mixer_object, "Mixer0",
            "masterVolume()", data, replyType, replydata);
    if (!has_mixer) {
        m_mixer_object = "kmix";
        has_mixer = kapp->dcopClient ()->call (m_mixer_object, "Mixer0",
                "masterVolume()", data, replyType, replydata);
    }
    if (has_mixer) {
        TQDataStream replystream (replydata, IO_ReadOnly);
        replystream >> volume;
        if (!m_mixer_init) {
            TQLabel * mixer_label = new TQLabel (i18n ("Volume:"), m_control_panel->popupMenu ());
            m_control_panel->popupMenu ()->insertItem (mixer_label, -1, 4);
            m_volume_slider = new TQSlider (0, 100, 10, volume, Qt::Horizontal, m_control_panel->popupMenu ());
            connect(m_volume_slider, TQT_SIGNAL(valueChanged(int)), this,TQT_SLOT(setVolume(int)));
            m_control_panel->popupMenu ()->insertItem (m_volume_slider, ControlPanel::menu_volume, 5);
            m_control_panel->popupMenu ()->insertSeparator (6);
        } else {
            m_inVolumeUpdate = true;
            m_volume_slider->setValue (volume);
            m_inVolumeUpdate = false;
        }
    } else if (m_volume_slider) {
        m_control_panel->popupMenu ()->removeItemAt (6);
        m_control_panel->popupMenu ()->removeItemAt (5);
        m_control_panel->popupMenu ()->removeItemAt (4);
        m_volume_slider = 0L;
    }
    m_mixer_init = true;
}

void View::showWidget (WidgetType wt) {
    m_widgetstack->raiseWidget (m_widgettypes [wt]);
    if (m_widgetstack->visibleWidget () == m_widgettypes[WT_Console]) {
        addText (TQString (""), false);
        if (m_controlpanel_mode == CP_AutoHide && m_playing)
            m_control_panel->show();
    } else
        delayedShowButtons (false);
    updateLayout ();
}

void View::toggleVideoConsoleWindow () {
    WidgetType wt = WT_Console;
    if (m_widgetstack->visibleWidget () == m_widgettypes[WT_Console]) {
        wt = WT_Video;
        m_control_panel->popupMenu ()->changeItem (ControlPanel::menu_video, TDEGlobal::iconLoader ()->loadIconSet (TQString ("konsole"), TDEIcon::Small, 0, true), i18n ("Con&sole"));
    } else
        m_control_panel->popupMenu ()->changeItem (ControlPanel::menu_video, TDEGlobal::iconLoader ()->loadIconSet (TQString ("video"), TDEIcon::Small, 0, true), i18n ("V&ideo"));
    showWidget (wt);
    emit windowVideoConsoleToggled (int (wt));
}

void View::setControlPanelMode (ControlPanelMode m) {
    killTimer (controlbar_timer);
    controlbar_timer = 0L;
    m_old_controlpanel_mode = m_controlpanel_mode = m;
    if (m_playing && isFullScreen())
        m_controlpanel_mode = CP_AutoHide;
    if ((m_controlpanel_mode == CP_Show || m_controlpanel_mode == CP_Only) &&
            !m_control_panel->isVisible ()) {
        m_control_panel->show ();
        m_view_area->resizeEvent (0L);
    } else if (m_controlpanel_mode == CP_AutoHide) { 
        if ((m_playing &&
                m_widgetstack->visibleWidget () != m_widgettypes[WT_Console]))
            delayedShowButtons (false);
        else if (!m_control_panel->isVisible ()) {
            m_control_panel->show ();
            m_view_area->resizeEvent (0L);
        }
    } else if (m_controlpanel_mode == CP_Hide && m_control_panel->isVisible()) {
        m_control_panel->hide ();
        m_view_area->resizeEvent (0L);
    }
}

void View::setStatusBarMode (StatusBarMode m) {
    m_statusbar_mode = m;
    if (m == SB_Hide)
        m_status_bar->hide ();
    else
        m_status_bar->show ();
    m_view_area->resizeEvent (0L);
}

KDE_NO_EXPORT void View::delayedShowButtons (bool show) {
    if ((show && m_control_panel->isVisible ()) || 
            (!show && !m_control_panel->isVisible ())) {
        if (controlbar_timer) {
            killTimer (controlbar_timer);
            controlbar_timer = 0;
        }
        if (!show)
            m_control_panel->hide (); // for initial race
    } else if (m_controlpanel_mode == CP_AutoHide &&
            (m_playing ||
             m_widgetstack->visibleWidget () == m_widgettypes[WT_Picture]) &&
            m_widgetstack->visibleWidget () != m_widgettypes[WT_Console] &&
            !controlbar_timer) {
        controlbar_timer = startTimer (500);
    }
}

KDE_NO_EXPORT void View::setVolume (int vol) {
    if (m_inVolumeUpdate) return;
    TQByteArray data;
    TQDataStream arg( data, IO_WriteOnly );
    arg << vol;
    if (!kapp->dcopClient()->send (m_mixer_object, "Mixer0", "setMasterVolume(int)", data))
        kdWarning() << "Failed to update volume" << endl;
}

KDE_NO_EXPORT void View::updateLayout () {
    if (m_controlpanel_mode == CP_Only)
        m_control_panel->setMaximumSize (2500, height ());
    m_view_area->resizeEvent (0L);
}

void View::setKeepSizeRatio (bool b) {
    if (m_keepsizeratio != b) {
        m_keepsizeratio = b;
        updateLayout ();
        m_view_area->update ();
    }
}

KDE_NO_EXPORT void View::timerEvent (TQTimerEvent * e) {
    if (e->timerId () == controlbar_timer) {
        controlbar_timer = 0;
        if (m_playing ||
                m_widgetstack->visibleWidget () == m_widgettypes[WT_Picture]) {
            int vert_buttons_pos = m_view_area->height()-statusBarHeight ();
            TQPoint mouse_pos = m_view_area->mapFromGlobal (TQCursor::pos ());
            int cp_height = m_control_panel->maximumSize ().height ();
            bool mouse_on_buttons = (//m_view_area->hasMouse () && 
                    mouse_pos.y () >= vert_buttons_pos-cp_height &&
                    mouse_pos.y ()<= vert_buttons_pos &&
                    mouse_pos.x () > 0 &&
                    mouse_pos.x () < m_control_panel->width());
            if (mouse_on_buttons && !m_control_panel->isVisible ()) {
                m_control_panel->show ();
                m_view_area->resizeEvent (0L);
            } else if (!mouse_on_buttons && m_control_panel->isVisible ()) {
                m_control_panel->hide ();
                m_view_area->resizeEvent (0L);
            }
        }
    } else if (e->timerId () == infopanel_timer) {
        if (m_infopanel->text ().isEmpty ())
            m_dock_infopanel->undock ();
        infopanel_timer  = 0;
    }
    killTimer (e->timerId ());
}

void View::addText (const TQString & str, bool eol) {
    if (m_tmplog_needs_eol)
        tmplog += TQChar ('\n');
    tmplog += str;
    m_tmplog_needs_eol = eol;
    if (m_widgetstack->visibleWidget () != m_widgettypes[WT_Console] &&
            tmplog.length () < 7500)
        return;
    if (eol) {
        m_multiedit->append (tmplog);
        tmplog.truncate (0);
        m_tmplog_needs_eol = false;
    } else {
        int pos = tmplog.findRev (TQChar ('\n'));
        if (pos >= 0) {
            m_multiedit->append (tmplog.left (pos));
            tmplog = tmplog.mid (pos+1);
        }
    }
    int p = m_multiedit->paragraphs ();
    if (5000 < p) {
        m_multiedit->setSelection (0, 0, p - 4499, 0);
        m_multiedit->removeSelectedText ();
    }
    m_multiedit->setCursorPosition (m_multiedit->paragraphs () - 1, 0);
}

/* void View::print (TQPrinter *pPrinter)
{
    TQPainter printpainter;
    printpainter.begin (pPrinter);

    // TODO: add your printing code here

    printpainter.end ();
}*/

KDE_NO_EXPORT void View::videoStart () {
    if (m_dockarea->getMainDockWidget () != m_dock_video) {
        // restore from an info or playlist only setting
        KDockWidget * dw = m_dockarea->getMainDockWidget ();
        dw->setEnableDocking (KDockWidget::DockCenter);
        dw->undock ();
        m_dock_video->setEnableDocking (KDockWidget::DockNone);
        m_dockarea->setMainDockWidget (m_dock_video);
        m_view_area->resizeEvent (0L);
    }
    if (m_controlpanel_mode == CP_Only) {
        m_control_panel->setMaximumSize(2500, controlPanel()->preferedHeight());
        setControlPanelMode (CP_Show);
    }
}

KDE_NO_EXPORT void View::playingStart () {
    if (m_playing) return; //FIXME: make symetric with playingStop
    if (m_widgetstack->visibleWidget () == m_widgettypes[WT_Picture])
        m_widgetstack->raiseWidget (m_viewer);
    m_playing = true;
    m_revert_fullscreen = !isFullScreen();
    setControlPanelMode (m_old_controlpanel_mode);
}

KDE_NO_EXPORT void View::playingStop () {
    if (m_controlpanel_mode == CP_AutoHide &&
            m_widgetstack->visibleWidget () != m_widgettypes[WT_Picture]) {
        m_control_panel->show ();
        //m_view_area->setMouseTracking (false);
    }
    killTimer (controlbar_timer);
    controlbar_timer = 0;
    m_playing = false;
    WId w = m_viewer->embeddedWinId ();
    if (w)
        XClearWindow (tqt_xdisplay(), w);
    m_view_area->resizeEvent (0L);
}

KDE_NO_EXPORT void View::leaveEvent (TQEvent *) {
    delayedShowButtons (false);
}

KDE_NO_EXPORT void View::reset () {
    if (m_revert_fullscreen && isFullScreen())
        m_control_panel->popupMenu ()->activateItemAt (m_control_panel->popupMenu ()->indexOf (ControlPanel::menu_fullscreen));
        //m_view_area->fullScreen ();
    playingStop ();
    m_viewer->show ();
}

bool View::isFullScreen () const {
    return m_view_area->isFullScreen ();
}

void View::fullScreen () {
    if (!m_view_area->isFullScreen()) {
        //if (m_keepsizeratio && m_viewer->aspect () < 0.01)
        //    m_viewer->setAspect (1.0 * m_viewer->width() / m_viewer->height());
        m_view_area->fullScreen();
        m_control_panel->popupMenu ()->setItemVisible (ControlPanel::menu_zoom, false);
        m_widgetstack->visibleWidget ()->setFocus ();
    } else {
        m_view_area->fullScreen();
        m_control_panel->popupMenu ()->setItemVisible (ControlPanel::menu_zoom, true);
    }
    setControlPanelMode (m_old_controlpanel_mode);
    emit fullScreenChanged ();
}

KDE_NO_EXPORT int View::statusBarHeight () const {
    if (statusBar()->isVisible () && !viewArea()->isFullScreen ()) {
        if (statusBarMode () == SB_Only)
            return height ();
        else 
            return statusBar()->maximumSize ().height ();
    }
    return 0;
}

bool View::x11Event (XEvent * e) {
    switch (e->type) {
        case UnmapNotify:
            if (e->xunmap.event == m_viewer->embeddedWinId ()) {
                videoStart ();
                //hide();
            }
            break;
        case XKeyPress:
            if (e->xkey.window == m_viewer->embeddedWinId ()) {
                KeySym ksym;
                char kbuf[16];
                XLookupString (&e->xkey, kbuf, sizeof(kbuf), &ksym, NULL);
                switch (ksym) {
                    case XK_f:
                    case XK_F:
                        //fullScreen ();
                        break;
                };
            }
            break;
        /*case ColormapNotify:
            fprintf (stderr, "colormap notify\n");
            return true;*/
        case MotionNotify:
            if (e->xmotion.window == m_viewer->embeddedWinId ())
                delayedShowButtons (e->xmotion.y > m_view_area->height () -
                        statusBarHeight () -
                        m_control_panel->maximumSize ().height ());
            m_view_area->mouseMoved ();
            break;
        case MapNotify:
            if (e->xmap.event == m_viewer->embeddedWinId ()) {
                show ();
                TQTimer::singleShot (10, m_viewer, TQT_SLOT (sendConfigureEvent ()));
            }
            break;
        /*case ConfigureNotify:
            break;
            //return true;*/
        default:
            break;
    }
    return false;
}

//----------------------------------------------------------------------

KDE_NO_CDTOR_EXPORT Viewer::Viewer (TQWidget *parent, View * view)
  : QXEmbed (parent), m_plain_window (0), m_bgcolor (0), m_aspect (0.0),
    m_view (view) {
    /*XWindowAttributes xwa;
    XGetWindowAttributes (tqt_xdisplay(), winId (), &xwa);
    XSetWindowAttributes xswa;
    xswa.background_pixel = 0;
    xswa.border_pixel = 0;
    xswa.colormap = xwa.colormap;
    create (XCreateWindow (tqt_xdisplay (), parent->winId (), 0, 0, 10, 10, 0, 
                           x11Depth (), InputOutput, (Visual*)x11Visual (),
                           CWBackPixel | CWBorderPixel | CWColormap, &xswa));*/
    setAcceptDrops (true);
    initialize ();
    //setProtocol (QXEmbed::XPLAIN);
}

KDE_NO_CDTOR_EXPORT Viewer::~Viewer () {
}

KDE_NO_EXPORT void Viewer::changeProtocol (QXEmbed::Protocol p) {
    kdDebug () << "changeProtocol " << (int)protocol () << "->" << p << endl;
    if (!embeddedWinId () || p != protocol ()) {
        if (p == QXEmbed::XPLAIN) {
            setProtocol (p);
            if (!m_plain_window) {
                int scr = DefaultScreen (tqt_xdisplay ());
                m_plain_window = XCreateSimpleWindow (
                        tqt_xdisplay(),
                        m_view->winId (),
                        0, 0, width(), height(),
                        1,
                        BlackPixel (tqt_xdisplay(), scr),
                        BlackPixel (tqt_xdisplay(), scr));
                embed (m_plain_window);
            }
            XClearWindow (tqt_xdisplay(), m_plain_window);
        } else {
            if (m_plain_window) {
                XDestroyWindow (tqt_xdisplay(), m_plain_window);
                m_plain_window = 0;
                XSync (tqt_xdisplay (), false);
            }
            //setProtocol (p);
            setProtocol (QXEmbed::XPLAIN);
        }
    }
}

KDE_NO_EXPORT void Viewer::windowChanged (WId w) {
    kdDebug () << "windowChanged " << (int)w << endl;
    if (w /*&& m_plain_window*/)
        XSelectInput (tqt_xdisplay (), w, 
                //KeyPressMask | KeyReleaseMask |
                KeyPressMask |
                //EnterWindowMask | LeaveWindowMask |
                //FocusChangeMask |
                ExposureMask |
                StructureNotifyMask |
                PointerMotionMask);
}

KDE_NO_EXPORT void Viewer::mouseMoveEvent (TQMouseEvent * e) {
    if (e->state () == Qt::NoButton) {
        int cp_height = m_view->controlPanel ()->maximumSize ().height ();
        m_view->delayedShowButtons (e->y () > height () - cp_height);
    }
    m_view->viewArea ()->mouseMoved ();
}

void Viewer::setAspect (float a) {
    m_aspect = a;
}

KDE_NO_EXPORT int Viewer::heightForWidth (int w) const {
    if (m_aspect <= 0.01)
        return 0;
    return int (w/m_aspect); 
}

KDE_NO_EXPORT void Viewer::dropEvent (TQDropEvent * de) {
    m_view->dropEvent (de);
}

KDE_NO_EXPORT void Viewer::dragEnterEvent (TQDragEnterEvent* dee) {
    m_view->dragEnterEvent (dee);
}
/*
*/
void Viewer::sendKeyEvent (int key) {
    WId w = embeddedWinId ();
    if (w) {
        char buf[2] = { char (key), '\0' }; 
        KeySym keysym = XStringToKeysym (buf);
        XKeyEvent event = {
            XKeyPress, 0, true,
            tqt_xdisplay (), w, tqt_xrootwin(), w,
            /*time*/ 0, 0, 0, 0, 0,
            0, XKeysymToKeycode (tqt_xdisplay (), keysym), true
        };
        XSendEvent (tqt_xdisplay(), w, false, KeyPressMask, (XEvent *) &event);
        XFlush (tqt_xdisplay ());
    }
}

KDE_NO_EXPORT void Viewer::sendConfigureEvent () {
    WId w = embeddedWinId ();
    if (w) {
        XConfigureEvent c = {
            ConfigureNotify, 0UL, True,
            tqt_xdisplay (), w, winId (),
            x (), y (), width (), height (),
            0, None, False
        };
        XSendEvent(tqt_xdisplay(),c.event,true,StructureNotifyMask,(XEvent*)&c);
        XFlush (tqt_xdisplay ());
    }
}

KDE_NO_EXPORT void Viewer::contextMenuEvent (TQContextMenuEvent * e) {
    m_view->controlPanel ()->popupMenu ()->exec (e->globalPos ());
}

KDE_NO_EXPORT void Viewer::setBackgroundColor (const TQColor & c) {
    if (m_bgcolor != c.rgb ()) {
        m_bgcolor = c.rgb ();
        setCurrentBackgroundColor (c);
    }
}

KDE_NO_EXPORT void Viewer::resetBackgroundColor () {
    setCurrentBackgroundColor (m_bgcolor);
}

KDE_NO_EXPORT void Viewer::setCurrentBackgroundColor (const TQColor & c) {
    setPaletteBackgroundColor (c);
    WId w = embeddedWinId ();
    if (w) {
        XSetWindowBackground (tqt_xdisplay (), w, c.rgb ());
        XFlush (tqt_xdisplay ());
    }
}

#include "kmplayerview.moc"
