/*
 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

 /*
   * This code is ported to XAWT from MAWT based on awt_mgrsel.c
   * and XSettings.java code written originally by Valeriy Ushakov
   * Author : Bino George
   */


package sun.awt.X11;

import java.util.*;
import java.awt.*;
import sun.awt.XSettings;
import sun.util.logging.PlatformLogger;


class XAWTXSettings extends XSettings implements XMSelectionListener {

    private final XAtom xSettingsPropertyAtom = XAtom.get("_XSETTINGS_SETTINGS");

    private static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XAWTXSettings");

    /* The maximal length of the property data. */
    public static final long MAX_LENGTH = 1000000;

    XMSelection settings;

    public XAWTXSettings() {
        initXSettings();

    }

    void initXSettings() {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Initializing XAWT XSettings");
        settings = new XMSelection("_XSETTINGS");
        settings.addSelectionListener(this);
        initPerScreenXSettings();
    }

    void dispose() {
        settings.removeSelectionListener(this);
    }

    public void ownerDeath(int screen, XMSelection sel, long deadOwner) {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Owner " + deadOwner + " died for selection " + sel + " screen "+ screen);
    }


    public void ownerChanged(int screen, XMSelection sel, long newOwner, long data, long timestamp) {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("New Owner "+ newOwner + " for selection = " + sel + " screen " +screen );
    }

    public void selectionChanged(int screen, XMSelection sel, long owner , XPropertyEvent event) {
        log.fine("Selection changed on sel " + sel + " screen = " + screen + " owner = " + owner + " event = " + event);
        updateXSettings(screen,owner);
    }

    void initPerScreenXSettings() {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Updating Per XSettings changes");

        /*
         * As toolkit cannot yet cope with per-screen desktop properties,
         * only report XSETTINGS changes on the default screen.  This
         * should be "good enough" for most cases.
         */

        Map updatedSettings = null;
        XToolkit.awtLock();
        try {
            long display = XToolkit.getDisplay();
            int screen = (int) XlibWrapper.DefaultScreen(display);
            updatedSettings = getUpdatedSettings(settings.getOwner(screen));
        } finally {
            XToolkit.awtUnlock();
        }
        // we must not  invoke this under Awt Lock
        ((XToolkit)Toolkit.getDefaultToolkit()).parseXSettings(0,updatedSettings);
    }

    private void updateXSettings(int screen, long owner) {
        final Map updatedSettings = getUpdatedSettings(owner);
        // this method is called under awt lock and usually on toolkit thread
        // but parseXSettings() causes public code execution, so we need to transfer
        // this to EDT
        EventQueue.invokeLater( new Runnable() {
            public void run() {
                ((XToolkit) Toolkit.getDefaultToolkit()).parseXSettings( 0, updatedSettings);
            }
        });
    }

    private Map getUpdatedSettings(final long owner) {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("owner =" + owner);
        if (0 == owner) {
            return null;
        }

        Map settings = null;
        try {
            WindowPropertyGetter getter =
                new WindowPropertyGetter(owner, xSettingsPropertyAtom, 0, MAX_LENGTH,
                        false, xSettingsPropertyAtom.getAtom() );
            try {
                int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

                if (status != XConstants.Success || getter.getData() == 0) {
                    if (log.isLoggable(PlatformLogger.FINE)) log.fine("OH OH : getter failed  status = " + status );
                    settings = null;
                }

                long ptr = getter.getData();

                if (log.isLoggable(PlatformLogger.FINE)) log.fine("noItems = " + getter.getNumberOfItems());
                byte array[] = Native.toBytes(ptr,getter.getNumberOfItems());
                if (array != null) {
                    settings = update(array);
                }
            } finally {
                getter.dispose();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return settings;
    }



}
