/*
 * Copyright (C) 1993 Rob Nation
 * Copyright (C) 1995 Bo Yang
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/**************************************************************************
 *
 * Assorted odds and ends
 *
 **************************************************************************/
#define LOCAL_DEBUG

#include "../../configure.h"

#include "asinternals.h"

/****************************************************************************/
/* window management specifics - button ungrabbing convinience functions:   */
/****************************************************************************/
inline void
ungrab_window_buttons( Window w )
{
	LOCAL_DEBUG_OUT( "w = %lX", w );
    XUngrabButton (dpy, AnyButton, AnyModifier, w);
}

inline void
ungrab_window_keys (Window w )
{
    XUngrabKey (dpy, AnyKey, AnyModifier, w);
}

/******************************************************************************
 * Versions of grab primitives that circumvent modifier problems
 *****************************************************************************/
void
MyXGrabButton ( unsigned button, unsigned modifiers,
                Window grab_window, Bool owner_events, unsigned event_mask,
                int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor)
{
	LOCAL_DEBUG_CALLER_OUT( "button = %d, w = %lX modifiers = %X", button, grab_window, modifiers );
    if( modifiers == AnyModifier )
        XGrabButton (dpy, button, AnyModifier, grab_window,
                     owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor);
    else
    {
        register int i = 0 ;
        do
        {
/*			LOCAL_DEBUG_OUT( "grabbing button %d with mod %lX on window %lX", button, modifiers | lock_mods[i], grab_window ); */
            XGrabButton (dpy, button, modifiers | lock_mods[i], grab_window,
                         owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor);
            if( lock_mods[i] == 0 )
                break;
        }while(++i < MAX_LOCK_MODS);
    }
}

void
MyXUngrabButton ( unsigned button, unsigned modifiers, Window grab_window)
{
	LOCAL_DEBUG_CALLER_OUT( "w = %lX", grab_window );
    if( modifiers == AnyModifier )
        XUngrabButton (dpy, button, AnyModifier, grab_window);
    else
    {
        register int i = 0 ;
        do
        {
            XUngrabButton (dpy, button, modifiers | lock_mods[i], grab_window);
            if( lock_mods[i] == 0 )
                break;
        }while(++i < MAX_LOCK_MODS);
    }
}

void
grab_window_buttons (Window w, ASFlagType context_mask)
{
    register MouseButton  *MouseEntry;
	LOCAL_DEBUG_OUT( "w = %lX, context = 0x%lX", w, context_mask );
    for( MouseEntry = Scr.Feel.MouseButtonRoot ; MouseEntry ; MouseEntry = MouseEntry->NextButton)
	{
        if ( MouseEntry->fdata  && get_flags(MouseEntry->Context, context_mask))
		{
		LOCAL_DEBUG_OUT( "mouse fdata %p button %d + modifier %X has context %lx", MouseEntry->fdata, MouseEntry->Button, MouseEntry->Modifier, get_flags(MouseEntry->Context, context_mask) );
			if (MouseEntry->Button > 0)
                MyXGrabButton (MouseEntry->Button, MouseEntry->Modifier, w,
							   True, ButtonPressMask | ButtonReleaseMask,
                               GrabModeAsync, GrabModeAsync, None, Scr.Feel.cursors[ASCUR_Default]);
            else
			{
                register int  i = MAX_MOUSE_BUTTONS+1;
                while( --i > 0 )
                    MyXGrabButton (i, MouseEntry->Modifier, w,
								   True, ButtonPressMask | ButtonReleaseMask,
                                   GrabModeAsync, GrabModeAsync, None, Scr.Feel.cursors[ASCUR_Default]);
            }
        }
	}
}


void
grab_focus_click( Window w )
{
    int i ;
    LOCAL_DEBUG_CALLER_OUT( "w = %lX", w );
	if( w )
    { /* need to grab all buttons for window that we are about to unfocus */
        for (i = 0; i < MAX_MOUSE_BUTTONS; i++)
            if (Scr.Feel.buttons2grab & (0x01 << i))
            {
                MyXGrabButton ( i + 1, 0, w, True, ButtonPressMask, GrabModeSync,
                                GrabModeAsync, None, Scr.Feel.cursors[ASCUR_Sys]);
            }
    }
}

void
ungrab_focus_click( Window w )
{
    LOCAL_DEBUG_CALLER_OUT( "w = %lX", w );
	if( w )
    {   /* if we do click to focus, remove the grab on mouse events that
         * was made to detect the focus change */
		register int i = 0;
#if 0        
        register ASFlagType grab_btn_mask = Scr.Feel.buttons2grab<<1 ;
        while ( ++i <= MAX_MOUSE_BUTTONS )
            if ( grab_btn_mask&(1<<i) )
			{
                MyXUngrabButton (i, 0, w);
			}
#else
        for (i = 0; i < MAX_MOUSE_BUTTONS; i++)
            if (Scr.Feel.buttons2grab & (0x01 << i))
            {
                MyXUngrabButton (i+1, 0, w);
			}
#endif				   
    }
}


/***********************************************************************
 * Key grabbing :
 ***********************************************************************/
void
grab_window_keys (Window w, ASFlagType context_mask)
{
	FuncKey      *tmp;
    for (tmp = Scr.Feel.FuncKeyRoot; tmp != NULL; tmp = tmp->next)
        if (get_flags( tmp->cont, context_mask ))
        {
            if( tmp->mods == AnyModifier )
                XGrabKey( dpy, tmp->keycode, AnyModifier, w, True, GrabModeAsync, GrabModeAsync);
            else
            {
                register int i = 0;
                do
                {/* combining modifiers with <Lock> keys,
                  * so to enable things like ScrollLock+Alt+A to work the same as Alt+A */
                    XGrabKey( dpy, tmp->keycode, tmp->mods|lock_mods[i], w, True, GrabModeAsync, GrabModeAsync);
                    if( lock_mods[i] == 0 )
                        break;
                }while(++i < MAX_LOCK_MODS);
            }
        }
}



/******************************************************************************
 *
 * Grab ClickToRaise button press events for a window
 *
 *****************************************************************************/
void
GrabRaiseClick (ASWindow * t)
{
	int           b;

	for (b = 1; b <= MAX_MOUSE_BUTTONS; b++)
	{
        if (Scr.Feel.RaiseButtons & (1 << b))
            MyXGrabButton (b, 0, t->w, True, ButtonPressMask, GrabModeSync,
                           GrabModeAsync, None, Scr.Feel.cursors[ASCUR_Title]);
	}
}

/******************************************************************************
 *
 * Ungrab ClickToRaise button press events to allow their use in applications
 *
 *****************************************************************************/
void
UngrabRaiseClick (ASWindow * t)
{
	int           b;

	for (b = 1; b <= MAX_MOUSE_BUTTONS; b++)
	{
        if (Scr.Feel.RaiseButtons & (1 << b))
            MyXUngrabButton (b, 0, t->w);
	}
}

/******************************************************************************
 *
 * Recalculate the visibility flags
 *
 *****************************************************************************/

void
UpdateVisibility (void)
{
#if 0
    ASWindow     *t, *s, *tbase;

	tbase = Scr.ASRoot.next;
	for (t = Scr.ASRoot.next; t != NULL; t = t->next)
	{
		int           visible = 0;
		int           tx1, ty1, tx2, ty2;

		if (t->flags & MAPPED)
		{
			tx1 = t->frame_x;
			ty1 = t->frame_y;
			if (t->flags & SHADED)
			{
				tx2 = t->frame_x + t->title_width;
				ty2 = t->frame_y + t->title_height;
			} else
			{
				tx2 = t->frame_x + t->frame_width;
				ty2 = t->frame_y + t->frame_height;
			}
		} else if (t->flags & ICONIFIED)
		{
			tx1 = t->icon_p_x;
			ty1 = t->icon_p_y;
			tx2 = t->icon_p_x + t->icon_p_width;
			ty2 = t->icon_p_y + t->icon_p_height;
		} else
			continue;

		if ((tx2 > 0) && (tx1 < Scr.MyDisplayWidth) && (ty2 > 0) && (ty1 < Scr.MyDisplayHeight))
		{
			visible = VISIBLE;
			for (s = Scr.ASRoot.next; s != t; s = s->next)
			{
				if (get_flags(s->hints->flags, AS_Transient) && (s->hints->transient_for == t->w))
					continue;
				else if (s->status->layer != t->status->layer)
					continue;

				if (s->flags & MAPPED)
				{
					if ((tx2 > s->frame_x) && (tx1 < s->frame_x + s->frame_width) &&
						(ty2 > s->frame_y) && (ty1 < s->frame_y + s->frame_height))
					{
						visible = 0;
						break;
					}
				} else if (s->flags & ICONIFIED)
				{
					if ((tx2 > s->icon_p_x) && (tx1 < s->icon_p_x + s->icon_p_width) &&
						(ty2 > s->icon_p_y) && (ty1 < s->icon_p_y + s->icon_p_height))
					{
						visible = 0;
						break;
					}
				} else if (s->flags & SHADED)
				{
					if ((tx2 > s->frame_x) && (tx1 < s->frame_x + s->title_width) &&
						(ty2 > s->frame_y) && (ty1 < s->frame_y + s->title_height))
					{
						visible = 0;
						break;
					}
				}
			}
		}
		if ((t->flags & VISIBLE) != visible)
		{
			t->flags ^= VISIBLE;
			if ((Scr.flags & ClickToRaise) && !(Scr.flags & ClickToFocus) && (t->flags & MAPPED))
			{
				if (visible)
					UngrabRaiseClick (t);
				else
					GrabRaiseClick (t);
			}
		}
	}
#endif
}


































































































































































