 /*-
 * 
 * This plugin was written by Andrew Sampson for the Golem window manager,
 * using code from the fspanel application and the Golem pager plugin 
 * 
 * Portions Copyright (c) 2000-2001 Peter Zelezny	(fspanel)
 * Portions Copyright (c) 2001 Jordan DeLong		(pager plugin)
 *
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
Parameters for this plugin ( see init() ):

param		: 
type		: 
values		: 
default		: 
description	: 

param		: at_top
type		: bool
values		: "true", "false"
default		: false
description	: determines where the taskbar will appear

param		: icons
type		: bool
values		: "true", "false"
default		: true
description	: determines if icons will be displayed


*/



#include "wm.h"
#include "taskbar.h"
#include "plugutil.h"

#ifdef HAVE_XPM
#include <X11/xpm.h>
#include "icon.xpm"
#endif

int scr_width;
int scr_depth;
XFontStruct *xfs;
int text_y;

Pixmap generic_icon;
Pixmap generic_mask;

/* global storage for  */
struct taskbar_global	*tb_global;


unsigned short cols[] = {
	0xd75c, 0xd75c, 0xd75c,		  /* 0. light gray */
	0xbefb, 0xbaea, 0xbefb,		  /* 1. mid gray */
	0xaefb, 0xaaea, 0xaefb,		  /* 2. dark gray */
	0xefbe, 0xefbe, 0xefbe,		  /* 3. white */
	0x8617, 0x8207, 0x8617,		  /* 4. darkest gray */
	0x0000, 0x0000, 0x0000		  /* 5. black */
};

#define PALETTE_COUNT (sizeof (cols) / sizeof (cols[0]) / 3)

unsigned long palette[PALETTE_COUNT];


/* new clients arriving */
static int window_birth( int pcall, client_t *client)
{
   //printf("window_birth\n");
   if( ( client->state == NormalState || client->state == IconicState ) && 
       !client->flags.internal )
   {
      taskbar_t *tb = tb_global->tb;

      if( client->workspace != NULL )
      {
         // printf("adding a task on workspace: %d\n", client->workspace );
        // printf("current: %d\n", client->screen->desktop->current_space );
      }
      else
      {
         // printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n");
      }
      
      
      taskbar_addtask( plugin_this, tb, client);
      taskbar_expose( tb, tb_global->drawgc, NULL);
   }

   return PLUGIN_OK;
}

/* old clients departing */
static int window_death( int pcall, client_t *client)
{
   taskbar_t *tb;
   
   tb = tb_global->tb;
   
   taskbar_rmtask( tb, NULL, client);
   taskbar_expose( tb, tb_global->drawgc, NULL);
   
   return PLUGIN_OK;
}

static int iconify_notify( int pcall, client_t *client)
{
   //printf("--- iconify_notify ----\n" );
   if (NULL == taskbar_findtask(tb_global->tb, client))
   {
      // printf("\tadding task\n" );
      if( client->workspace == NULL )
      {
         //  printf("....... null workspace ..........\n" );
      }
      taskbar_addtask(plugin_this, tb_global->tb, client);
   }
		
   if (client->workspace && !client->flags.internal)
   {      
      taskbar_t *tb = tb_global->tb;
      // printf("\texposing taskbar\n");
      taskbar_expose( tb, tb_global->drawgc, NULL);
   }
   
   return PLUGIN_OK;
}

static int restore_notify( int pcall, client_t *client)
{
   
   if (client->workspace && !client->flags.internal)
   {
      taskbar_t *tb = tb_global->tb;
      taskbar_expose( tb, tb_global->drawgc, NULL);
   }
   
   return PLUGIN_OK;
}



/* desktop changing */
static int desktop_change( int pcall, screen_t *screen, desktop_t *olddesk)
{
	taskbar_expose( tb_global->tb, tb_global->drawgc, NULL );

	return PLUGIN_OK;
}

/* workspace changing */
static int workspace_change( int pcall, screen_t *screen, desktop_t *desktop) {

	taskbar_expose( tb_global->tb, tb_global->drawgc, NULL );

	return PLUGIN_OK;
}


static int focus_change( int pcall, client_t *client) {

	if (client->workspace && !client->flags.internal) {
	        taskbar_t *tb = tb_global->tb;
		taskbar_expose( tb, tb_global->drawgc, NULL);
	}

	return PLUGIN_OK;
}


static int property_notify( int pcall, client_t *client) {

	if (client->workspace && !client->flags.internal) {
	        taskbar_t *tb = tb_global->tb;
		taskbar_client_propertynotify( tb, NULL, client );
                taskbar_expose( tb, tb_global->drawgc, NULL);
	}

	return PLUGIN_OK;
}




/* exposures on our taskbar windows */
static int tb_expose( XExposeEvent *e )
{        
	taskbar_expose( tb_global->tb, tb_global->drawgc, e );

	return PLUGIN_OK;
}

/* presses */
static int tb_button_press( XButtonEvent *e ) {	

// not needed

	return PLUGIN_OK;
}

/* releases */
static int tb_button_release(XButtonEvent *e) {

	/* pass button1 clicks on to taskbar_click */
	if( e->button == Button1 )
    {
		taskbar_click( tb_global->tb, e->x, e->y );
	}

	return PLUGIN_OK;
}


/*
 * x event handler for windows we deal with; just
 * call out to the appropriate handler.
 */
int xevent_handler( XEvent *e ) {

	if( e == NULL ) {
          printf( "taskbar: got a NULL XEvent\n" );
            return PLUGIN_OK;
        }

        switch (e->type) {
	case Expose:
		tb_expose(&e->xexpose);
		break;
	case NoExpose:
		/* I hate X11 */
		break;
	case ButtonPress:
		tb_button_press(&e->xbutton);
		break;
	case ButtonRelease:
		tb_button_release(&e->xbutton);
		break;
	default:
//PTRACE causes segfaults (WTF?)
//		PTRACE("unhandled event %d", e->type);
		printf( "unhandled event %d\n", e->type );
                break;
	}

	return PLUGIN_OK;
}


/* get parameters, init taskbar system */
int init()
{
	int icons;
    int at_top;

	/* get our parameters */
	OPTIONAL_PARAM(&plugin_this->params, "at_top", bool, at_top, 0);
	OPTIONAL_PARAM(&plugin_this->params, "icons",  bool, icons,  1);

	/* set up the taskbar system */
	taskbar_initialize( at_top, icons );

	return PLUGIN_OK;
}

/* handle plugin shutdowns */
void shutdown() {

	/* clear up the stuff */
	taskbar_delete( tb_global->tb );
	XFreeGC( display, tb_global->drawgc );
	free( tb_global );

	/* grid colors aren't yet free */
//fixme - what about tb_global->*_color

}

/* start up our taskbars, make our screen structures, etc */
int start()
{
	XGCValues gcvalues;
	XColor clr;
	screen_t *screen;
//	desktop_t *desktop;
	int i, j;
        char* fontname;


	plugin_callback_add(plugin_this, PCALL_WINDOW_BIRTH, window_birth);
	plugin_callback_add(plugin_this, PCALL_WINDOW_DEATH, window_death);
	plugin_callback_add(plugin_this, PCALL_ICONIFY_NOTIFY, iconify_notify );
	plugin_callback_add(plugin_this, PCALL_RESTORE_NOTIFY, restore_notify );
//	plugin_callback_add(plugin_this, PCALL_FOCUS_CHANGE, focus_change);
	plugin_callback_add(plugin_this, PCALL_DESKTOP_CHANGE, desktop_change);
	plugin_callback_add(plugin_this, PCALL_WORKSPACE_CHANGE, workspace_change);
        plugin_callback_add(plugin_this, PCALL_PROPERTY_NOTIFY, property_notify );
	i = j = 0;
	do
	{
		clr.red = cols[i];
		i++;
		clr.green = cols[i];
		i++;
		clr.blue = cols[i];
		i++;
		XAllocColor( display, 
                             DefaultColormap (display, DefaultScreen(display)), &clr );
		palette[j] = clr.pixel;
		j++;
	}
	while (j < PALETTE_COUNT);

	fontname = FONT_NAME;
	do
	{
		xfs = XLoadQueryFont (display, fontname);
		fontname = "fixed";
	}
	while (!xfs);
	text_y = xfs->ascent + ((TASKBAR_HEIGHT - xfs->ascent) / 2);
	gcvalues.font = xfs->fid;


	/* alloc the thingy */
	tb_global = malloc( sizeof(struct taskbar_global) );
	if (!tb_global)
		return PLUGIN_UNLOAD;

	tb_global->drawgc = 
            XCreateGC( display, RootWindow(display, DefaultScreen(display)),
				GCForeground, &gcvalues );

	/* make one taskbar */
        screen = TAILQ_FIRST(&screen_list);
	tb_global->tb = taskbar_create( plugin_this, screen, NULL );
	if ( !tb_global->tb )
		return PLUGIN_UNLOAD;

#ifdef HAVE_XPM
	XpmCreatePixmapFromData(display, 
                                RootWindow(display, DefaultScreen(display)), 
        			icon_xpm, &generic_icon,
				&generic_mask, NULL);

#else
	generic_icon = None;
	generic_mask = None;
#endif

	return PLUGIN_OK;
}



