/* util header */

/*
 * Copyright (C) 2001 Havoc Pennington
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gdk/gdkx.h>
#include <libxfce4util/libxfce4util.h>

#include "netk-util.h"
#include "netk-xutils.h"
#include "netk-private.h"

#if 0  /* unused? */
static void
set_type_realize_handler (GtkWidget * widget, gpointer data)
{
    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDK_IS_WINDOW(widget->window));
    g_return_if_fail (data != NULL);

    p_netk_set_type_hint (GDK_WINDOW_XWINDOW (widget->window), (NetkWindowType) GPOINTER_TO_INT(data));
}
#endif

GType
_netk_g_type_register_simple (GType        type_parent,
                              const gchar *type_name_static,
                              guint        class_size,
                              gpointer     class_init,
                              guint        instance_size,
                              gpointer     instance_init,
                              GTypeFlags   flags)
{
  /* setup the type info on the stack */
  GTypeInfo info =
  {
    class_size,
    NULL,
    NULL,
    (GClassInitFunc) class_init,
    NULL,
    NULL,
    instance_size,
    0,
    (GInstanceInitFunc) instance_init,
    NULL,
  };

  /* register the new type */
  return g_type_register_static (type_parent, I_(type_name_static), &info, 0);
}

void
netk_gtk_window_set_type (GtkWindow * window, NetkWindowType type)
{
    g_return_if_fail (window != NULL);
    
    /* GTK 2.4.x has properties for that */
#if GTK_CHECK_VERSION(2, 2, 0)
    switch (type)
    {
        case NETK_WINDOW_DESKTOP:
            DBG ("type NETK_WINDOW_DESKTOP");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_DESKTOP, NULL);
            break;
        case NETK_WINDOW_DOCK:
            DBG ("type NETK_WINDOW_DOCK");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_DOCK, NULL);
            break;
        case NETK_WINDOW_MODAL_DIALOG:
            DBG ("type NETK_WINDOW_MODAL_DIALOG");
            g_object_set (G_OBJECT(window), "modal", TRUE, NULL);
        case NETK_WINDOW_DIALOG:
            DBG ("type NETK_WINDOW_DIALOG");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_DIALOG, NULL);
            break;
        case NETK_WINDOW_TOOLBAR:
            DBG ("type NETK_WINDOW_TOOLBAR");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_TOOLBAR, NULL);
            break;
        case NETK_WINDOW_MENU:
            DBG ("type NETK_WINDOW_MENU");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_MENU, NULL);
            break;
        case NETK_WINDOW_UTILITY:
            DBG ("type NETK_WINDOW_UTILITY");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_UTILITY, NULL);
            break;
        case NETK_WINDOW_SPLASHSCREEN:
            DBG ("type NETK_WINDOW_SPLASHSCREEN");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_SPLASHSCREEN, NULL);
            break;
        default:
            DBG ("default, using NETK_WINDOW_NORMAL");
            g_object_set (G_OBJECT(window), "type-hint", GDK_WINDOW_TYPE_HINT_NORMAL, NULL);
            break;
    }
#else    
    if (GTK_WIDGET_REALIZED (window))
    {
        set_type_realize_handler (GTK_WIDGET (window), GINT_TO_POINTER(type));
    }
    g_signal_connect (GTK_WINDOW (window), "realize",
                      G_CALLBACK (set_type_realize_handler), GINT_TO_POINTER(type));
#endif
}

static void
set_no_input_realize_handler (GtkWidget * widget, gpointer data)
{
    XWMHints *wmhints;
    Atom *protocols = None;
    int n;

        g_return_if_fail (widget != NULL);
    g_return_if_fail (GDK_IS_WINDOW(widget->window));

    wmhints =
        XGetWMHints (GDK_WINDOW_XDISPLAY (widget->window),
                     GDK_WINDOW_XWINDOW (widget->window));
    
    if (!wmhints && !(wmhints = XAllocWMHints()))
        return;
    
    wmhints->flags |= InputHint;
    wmhints->input = False;
    XSetWMHints (GDK_WINDOW_XDISPLAY (widget->window),
                 GDK_WINDOW_XWINDOW (widget->window), wmhints);
    XFree (wmhints);

    if (XGetWMProtocols
        (GDK_WINDOW_XDISPLAY (widget->window),
         GDK_WINDOW_XWINDOW (widget->window), &protocols, &n))
    {
        Atom *replace_protocols, *ap, *bp;
        Atom wm_takefocus;
        int i, m;

        replace_protocols = g_new (Atom, n);
        wm_takefocus =
            XInternAtom (GDK_WINDOW_XDISPLAY (widget->window),
                         "WM_TAKE_FOCUS", False);
        for (i = 0, m = 0, ap = protocols, bp = replace_protocols; i < n;
             i++, ap++)
        {
            if (*ap != (Atom) wm_takefocus)
            {
                *bp = *ap;
                bp++;
                m++;
            }
        }
        XSetWMProtocols (GDK_WINDOW_XDISPLAY (widget->window),
                         GDK_WINDOW_XWINDOW (widget->window),
                         replace_protocols, m);
        XFree (protocols);
        g_free (replace_protocols);
    }
}

void
netk_gtk_window_avoid_input (GtkWindow * window)
{
    g_return_if_fail (window != NULL);

    /* GTK 2.4.x has properties for that */
    if ((gtk_major_version >=2) && (gtk_minor_version >= 3))
    {
        g_object_set (G_OBJECT(window), "accept-focus", FALSE, NULL);
    }
    else
    {
        if (GTK_WIDGET_REALIZED (window))
        {
            set_no_input_realize_handler (GTK_WIDGET (window), NULL);
        }
        g_signal_connect_after (GTK_WINDOW (window), "realize",
                          G_CALLBACK (set_no_input_realize_handler), NULL);
    }
}

/**
 * _make_gtk_label_bold.
 *
 * Switches the font of label to a bold equivalent.
 * @label: The label.
 **/
void
p_make_gtk_label_bold (GtkLabel *label)
{
  PangoFontDescription *font_desc;

  font_desc = pango_font_description_new ();

  pango_font_description_set_weight (font_desc,
                                     PANGO_WEIGHT_BOLD);

  /* This will only affect the weight of the font, the rest is
   * from the current state of the widget, which comes from the
   * theme or user prefs, since the font desc only has the
   * weight flag turned on.
   */
  gtk_widget_modify_font (GTK_WIDGET (label), font_desc);

  pango_font_description_free (font_desc);
}

void
p_make_gtk_label_normal (GtkLabel *label)
{
  /* This will only affect the weight of the font, the rest is
   * from the current state of the widget, which comes from the
   * theme or user prefs, since the font desc only has the
   * weight flag turned on.
   */
  gtk_widget_modify_font (GTK_WIDGET (label), NULL);
}

void
p_netk_init (void)
{
    static gboolean done = FALSE;

    if (!done)
    {
        done = TRUE;
    }
}

gboolean
netk_get_cardinal (Window xwindow, Atom atom, int *val)
{
    return p_netk_get_cardinal (xwindow, atom, val);
}

int
netk_get_wm_state (Window xwindow)
{
    return p_netk_get_wm_state (xwindow);
}

gboolean
netk_get_window (Window xwindow, Atom atom, Window * val)
{
    return p_netk_get_window (xwindow, atom, val);
}

gboolean
netk_get_pixmap (Window xwindow, Atom atom, Pixmap * val)
{
    return p_netk_get_pixmap (xwindow, atom, val);
}

gboolean
netk_get_atom (Window xwindow, Atom atom, Atom * val)
{
    return p_netk_get_atom (xwindow, atom, val);
}

char *
netk_get_text_property (Window xwindow, Atom atom)
{
    return p_netk_get_text_property (xwindow, atom);
}

char *
netk_get_utf8_property (Window xwindow, Atom atom)
{
    return p_netk_get_utf8_property (xwindow, atom);
}

gboolean
netk_get_window_list (Window xwindow, Atom atom, Window ** windows, int *len)
{
    return p_netk_get_window_list (xwindow, atom, windows, len);
}

gboolean
netk_get_atom_list (Window xwindow, Atom atom, Atom ** atoms, int *len)
{
    return p_netk_get_atom_list (xwindow, atom, atoms, len);
}

gboolean
netk_get_cardinal_list (Window xwindow, Atom atom, gulong ** cardinals,
                        int *len)
{
    return p_netk_get_cardinal_list (xwindow, atom, cardinals, len);
}

char **
netk_get_utf8_list (Window xwindow, Atom atom)
{
    return p_netk_get_utf8_list (xwindow, atom);
}

void
netk_close (Screen * screen, Window xwindow)
{
    p_netk_close (screen, xwindow);
}

void
netk_change_state (Screen * screen, Window xwindow, gboolean add, Atom state1,
                   Atom state2)
{
    p_netk_change_state (screen, xwindow, add, state1, state2);
}

void
netk_change_workspace (Screen * screen, Window xwindow, int new_space)
{
    p_netk_change_workspace (screen, xwindow, new_space);
}

void
netk_activate (Screen * screen, Window xwindow)
{
    p_netk_activate (screen, xwindow);
}

void
netk_activate_workspace (Screen * screen, int new_active_space)
{
    p_netk_activate_workspace (screen, new_active_space);
}

Window
netk_get_group_leader (Window xwindow)
{
    return p_netk_get_group_leader (xwindow);
}

char *
netk_get_session_id (Window xwindow)
{
    return p_netk_get_session_id (xwindow);
}

int
netk_get_pid (Window xwindow)
{
    return p_netk_get_pid (xwindow);
}

char *
netk_get_name (Window xwindow)
{
    return p_netk_get_name (xwindow);
}

char *
netk_get_res_class_utf8 (Window xwindow)
{
    return p_netk_get_res_class_utf8 (xwindow);
}

void
netk_set_desktop_layout (Screen * xscreen, int rows, int columns)
{
    p_netk_set_desktop_layout (xscreen, rows, columns);
}

gboolean
netk_get_desktop_margins (Screen * xscreen, DesktopMargins * margins)
{
    return p_netk_get_desktop_margins (xscreen, (p_DesktopMargins *) margins);
}

void
netk_set_desktop_margins (Window xwindow, DesktopMargins * margins)
{
    p_netk_set_desktop_margins (xwindow, (p_DesktopMargins *) margins);
}
