/* screen.c - screen management
 * 
 *  WindowMaker window manager
 * 
 *  Copyright (c) 1997 Alfredo K. Kojima
 * 
 *  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.
 */

#include "wconfig.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif

#include <wraster.h>

#include "generic/wwmlib.h"
#include "WindowMaker.h"
#include "def_pixmaps.h"
#include "screen.h"
#include "texture.h"
#include "pixmap.h"
#include "menu.h"
#include "funcs.h"
#include "actions.h"
#include "properties.h"
#include "dock.h"
#include "resources.h"
#include "workspace.h"

#include <proplist.h>

#include "defaults.h"


#define EVENT_MASK (LeaveWindowMask|EnterWindowMask|PropertyChangeMask\
		|SubstructureNotifyMask|PointerMotionMask \
		|SubstructureRedirectMask|ButtonPressMask|ButtonReleaseMask\
		|KeyPressMask|KeyReleaseMask)


#define STIPPLE_WIDTH 2
#define STIPPLE_HEIGHT 2
static char STIPPLE_DATA[] = {0x02, 0x01};


/**** Global variables ****/

extern Cursor wCursor[WCUR_LAST];
extern WPreferences wPreferences;
extern Atom _XA_WINDOWMAKER_STATE;

/*
 *----------------------------------------------------------------------
 * alreadyRunningError--
 * 	X error handler used to catch errors when trying to do
 * XSelectInput() on the root window. These errors probably mean that
 * there already is some other window manager running.
 * 
 * Returns:
 * 	Nothing, unless something really evil happens...
 * 
 * Side effects:
 * 	The program is aborted.
 *---------------------------------------------------------------------- 
 */
static int 
alreadyRunningError(Display *dpy, XErrorEvent *error)
{
    wFatal(_("it seems that there already is a window manager running"));
    exit(1);
    return -1;
}


/*
 *---------------------------------------------------------------------- 
 * allocButtonPixmaps--
 * 	Allocate pixmaps used on window operation buttons (those in the
 * titlebar). The pixmaps are linked to the program. If XPM is supported
 * XPM pixmaps are used otherwise, equivalent bitmaps are used.
 * 
 * Returns:
 * 	Nothing
 * 
 * Side effects:
 * 	Allocates shared pixmaps for the screen. These pixmaps should 
 * not be freed by anybody.
 *---------------------------------------------------------------------- 
 */
static void
allocButtonPixmaps(WScreen *scr)
{
    WPixmap *pix;

    /* create predefined pixmaps */
    pix = wPixmapCreateFromXPMData(scr, PRED_CLOSE_XPM);
    if (pix)
      pix->shared = 1;
    scr->b_pixmaps[WBUT_CLOSE] = pix;

    pix = wPixmapCreateFromXPMData(scr, PRED_BROKEN_CLOSE_XPM);
    if (pix)
      pix->shared = 1;
    scr->b_pixmaps[WBUT_BROKENCLOSE] = pix;

    pix = wPixmapCreateFromXPMData(scr, PRED_ICONIFY_XPM);
    if (pix)
      pix->shared = 1;
    scr->b_pixmaps[WBUT_ICONIFY] = pix;
}


#ifdef DOCK

static void
draw_dot(WScreen *scr, Drawable d, int x, int y, GC gc)
{
    XSetForeground(dpy, gc, scr->black_pixel);
    XDrawLine(dpy, d, gc, x, y, x+1, y);
    XDrawPoint(dpy, d, gc, x, y+1);
    XSetForeground(dpy, gc, scr->white_pixel);
    XDrawLine(dpy, d, gc, x+2, y, x+2, y+1);
    XDrawPoint(dpy, d, gc, x+1, y+1);
}

static WPixmap*
make3Dots(WScreen *scr)
{
    WPixmap *wpix;
    GC gc2, gc;
    XGCValues gcv;
    Pixmap pix, mask;
    
    gc = scr->copy_gc;
    pix = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, 
			wPreferences.icon_size,	scr->w_depth);
    XSetForeground(dpy, gc, scr->black_pixel);
    XFillRectangle(dpy, pix, gc, 0, 0, wPreferences.icon_size, 
		   wPreferences.icon_size);
    XSetForeground(dpy, gc, scr->white_pixel);
    draw_dot(scr, pix, 4, wPreferences.icon_size-6, gc);
    draw_dot(scr, pix, 9, wPreferences.icon_size-6, gc);
    draw_dot(scr, pix, 14, wPreferences.icon_size-6, gc);

    mask = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, 
			 wPreferences.icon_size, 1);
    gcv.foreground = 0;
    gc2 = XCreateGC(dpy, mask, GCForeground, &gcv);
    XFillRectangle(dpy, mask, gc2, 0, 0, wPreferences.icon_size, 
		   wPreferences.icon_size);
    XSetForeground(dpy, gc2, 1);
    XFillRectangle(dpy, mask, gc2, 4, wPreferences.icon_size-6, 3, 2);
    XFillRectangle(dpy, mask, gc2, 9, wPreferences.icon_size-6, 3, 2);
    XFillRectangle(dpy, mask, gc2, 14, wPreferences.icon_size-6, 3, 2);
    
    XFreeGC(dpy, gc2);
    
    wpix = wPixmapCreate(scr, pix, mask);
    wpix->shared = 1;

    return wpix;
}

#if 0
static WPixmap*
makeTBolt(WScreen *scr)
{
    WPixmap *pix;
    GC gc2, gc;
    XGCValues gcv;
    Pixmap p, m;
#if 0
    pix = wmalloc(sizeof(WPixmap));
    memset(pix, 0, sizeof(WPixmap));
    pix->shared = 1;
    pix->width = wPreferences.icon_size;
    pix->height = wPreferences.icon_size;
    pix->depth = scr->w_depth;
    gc = scr->copy_gc;
    pix->image = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, 
			       wPreferences.icon_size, scr->w_depth);
    XSetForeground(dpy, gc, scr->black_pixel);

    pix->mask = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, 
			      wPreferences.icon_size, 1);
    gcv.foreground = 0;
    gc2 = XCreateGC(dpy, pix->mask, GCForeground, &gcv);
    XFillRectangle(dpy, pix->mask, gc2, 0, 0, wPreferences.icon_size, 
		   wPreferences.icon_size);
    XSetForeground(dpy, gc2, 1);
    XDrawLine(dpy, pix->mask, gc2, wPreferences.icon_size - 4, 4, 
	      wPreferences.icon_size - 7, 7);
    XDrawLine(dpy, pix->mask, gc2, wPreferences.icon_size - 5, 7, 
	      wPreferences.icon_size - 8, 11);
    XDrawPoint(dpy, pix->mask, gc2, wPreferences.icon_size - 6, 7);
    XFreeGC(dpy, gc2);
#endif 
    gc = scr->copy_gc;
    p = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, 
		      wPreferences.icon_size, scr->w_depth);
    XSetForeground(dpy, gc, scr->black_pixel);
    XFillRectangle(dpy, p, gc, 0, 0, wPreferences.icon_size, 
		   wPreferences.icon_size);
    XSetForeground(dpy, gc, scr->white_pixel);
    XDrawLine(dpy, p, gc, wPreferences.icon_size - 4, 5, 
	      wPreferences.icon_size - 3, 5);
    XDrawPoint(dpy, p, gc, wPreferences.icon_size - 3, 4);

    m = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, 
		      wPreferences.icon_size, 1);
    gcv.foreground = 0;
    gc2 = XCreateGC(dpy, m, GCForeground, &gcv);
    XFillRectangle(dpy, m, gc2, 0, 0, wPreferences.icon_size, 
		   wPreferences.icon_size);
    XSetForeground(dpy, gc2, 1);
    XFillRectangle(dpy, m, gc2, wPreferences.icon_size - 5, 4, 3, 2);
    
    XFreeGC(dpy, gc2);

    pix = wPixmapCreate(scr, p, m);
    pix->shared = 1;

    return pix;
}
#endif
#endif /* DOCK */



static void
allocGCs(WScreen *scr)
{
    XGCValues gcv;
    XColor color;
    unsigned long mtextcolor;
    int gcm;

    scr->stipple_bitmap = 
      XCreateBitmapFromData(dpy, scr->w_win, STIPPLE_DATA, STIPPLE_WIDTH,
			    STIPPLE_HEIGHT);

    gcv.stipple = scr->stipple_bitmap;
    gcv.foreground = scr->white_pixel;
    gcv.fill_style = FillStippled;
    gcm = GCForeground|GCStipple|GCFillStyle;
    scr->stipple_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);

    
    gcm = GCForeground;
    
    scr->menu_title_pixel[0] = scr->white_pixel;
    gcv.foreground = scr->white_pixel;
    scr->menu_title_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);

    scr->mtext_pixel = scr->black_pixel;
    mtextcolor = gcv.foreground = scr->black_pixel;
    scr->menu_entry_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);

    /* selected menu entry GC */
    gcm = GCForeground|GCBackground;
    gcv.foreground = scr->white_pixel;
    gcv.background = scr->white_pixel;
    scr->select_menu_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);

    
    scr->dtext_pixel = scr->black_pixel;
    gcm = GCForeground|GCBackground|GCStipple;
    gcv.foreground = color.pixel;
    gcv.stipple = scr->stipple_bitmap;

    scr->disabled_menu_entry_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);

    /* frame GC */
    wGetColor(scr, DEF_FRAME_COLOR, &color);

    gcv.foreground = color.pixel;
    gcv.function = GXxor;
    gcv.line_width = DEF_FRAME_THICKNESS;
    gcv.subwindow_mode = IncludeInferiors;
    scr->frame_gc = XCreateGC(dpy, scr->root_win, GCForeground
			      |GCFunction|GCSubwindowMode|GCLineWidth, &gcv);
    
    /* line GC */
    gcv.foreground = color.pixel;
    gcv.function = GXxor;
    gcv.subwindow_mode = IncludeInferiors;
    gcm = GCForeground|GCFunction|GCSubwindowMode;
    scr->line_gc = XCreateGC(dpy, scr->root_win, gcm, &gcv);

    scr->line_pixel = color.pixel;
    
    /* copy GC */
    gcv.foreground = scr->white_pixel;
    gcv.background = scr->black_pixel;
    scr->copy_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground, &gcv);
    

    /* window title text GC */
    scr->window_title_gc = XCreateGC(dpy, scr->w_win, 0, NULL);

    /* icon title GC */
    scr->icon_title_gc = XCreateGC(dpy, scr->w_win, 0, NULL);

    /* move/size display GC */
    gcv.foreground = scr->black_pixel;
    gcm = GCForeground;
    scr->info_text_gc = XCreateGC(dpy, scr->root_win, gcm, &gcv);
}


static void
createPixmaps(WScreen *scr)
{
    WPixmap *pix;
    WMPixmap *wmpix;
    RImage *image;
    Pixmap p, m;

    /* load pixmaps */
    pix = wPixmapCreateFromXBMData(scr, (char*)MENU_INDICATOR_XBM_DATA, 
				   (char*)MENU_INDICATOR_XBM_DATA,
				   MENU_INDICATOR_XBM_SIZE,
				   MENU_INDICATOR_XBM_SIZE,
				   scr->black_pixel, scr->white_pixel);
    if (pix!=NULL)
      pix->shared = 1;
    scr->menu_indicator = pix;

    
    pix = wPixmapCreateFromXBMData(scr, (char*)MENU_INDICATOR2_XBM_DATA,
				   (char*)MENU_INDICATOR2_XBM_DATA,
				   MENU_INDICATOR2_XBM_SIZE,
				   MENU_INDICATOR2_XBM_SIZE,
				   scr->black_pixel, scr->white_pixel);
    if (pix!=NULL)
      pix->shared = 1;
    scr->menu_indicator2 = pix;


    image = wGetImageForWindowName(scr, "WMPanel", "Logo");

    if (!image) {
	wWarning(_("could not load logo image for panels"));
    } else {
	if (!RConvertImageMask(scr->rcontext, image, &p, &m, 128)) {
	    wWarning(_("error making logo iamge for panel:%s"), RErrorString);
	} else {
	    wmpix = WMCreatePixmapFromXPixmaps(scr->wmscreen, p, m,
					       image->width, image->height, 
					       scr->depth);
	    WMSetApplicationIcon(scr->wmscreen, wmpix); WMReleasePixmap(wmpix);
	}
	RDestroyImage(image);
    }
    
#ifdef DOCK
    if (!wPreferences.flags.nodock) {
	scr->dock_dots = make3Dots(scr);
	/*
	scr->dock_tbolt = makeTBolt(scr);
	 */
    }
#endif
    /* titlebar button pixmaps */
    allocButtonPixmaps(scr);
}


/*
 *----------------------------------------------------------------------
 * createInternalWindows--
 * 	Creates some windows used internally by the program. One to
 * receive input focus when no other window can get it and another
 * to display window geometry information during window resize/move.
 * 
 * Returns:
 * 	Nothing
 * 
 * Side effects:
 * 	Windows are created and some colors are allocated for the
 * window background.
 *---------------------------------------------------------------------- 
 */
static void
createInternalWindows(WScreen *scr)
{
    int vmask;
    int bfw;
    XSetWindowAttributes attribs;

#ifdef I18N_MB
    bfw = XmbTextEscapement(scr->info_text_font->font, "-8888 x -8888", 13);
#else
    bfw = XTextWidth(scr->info_text_font->font, "-8888 x -8888", 13);
#endif

    /* window for displaying geometry information during resizes and moves */
    vmask = CWBackPixmap|CWBackPixel|CWCursor|CWSaveUnder|CWOverrideRedirect;
    attribs.save_under = True;
    attribs.override_redirect = True;    
    attribs.cursor = wCursor[WCUR_DEFAULT];
    attribs.background_pixmap = None;
    attribs.background_pixel = scr->window_title_texture[WS_UNFOCUSED]->any.color.pixel;
    scr->geometry_display =
      XCreateWindow(dpy, scr->root_win, (scr->scr_width-bfw)/2, 
		    (scr->scr_height-20)/2, bfw, 20, 1, scr->depth, 
		    CopyFromParent, scr->w_visual, vmask, &attribs);
    
    /* InputOnly window to get the focus when no other window can get it */
    vmask = CWEventMask|CWOverrideRedirect;
    attribs.event_mask = KeyPressMask|FocusChangeMask;
    attribs.override_redirect = True;
    scr->no_focus_win=XCreateWindow(dpy,scr->root_win,-10, -10, 4, 4, 0, 0,
				    InputOnly,CopyFromParent, vmask, &attribs);
    XSelectInput(dpy, scr->no_focus_win, KeyPressMask|KeyReleaseMask);
    XMapWindow(dpy, scr->no_focus_win);

    XSetInputFocus (dpy, scr->no_focus_win, RevertToParent, CurrentTime);
 
#ifdef DOCK
    /* shadow window for dock buttons */
    vmask = CWBackPixmap|CWBackPixel|CWCursor|CWSaveUnder|CWOverrideRedirect;
    attribs.save_under = True;
    attribs.override_redirect = True;
    attribs.background_pixmap = None;
    attribs.background_pixel = scr->white_pixel;
    scr->dock_shadow =
      XCreateWindow(dpy, scr->root_win, 0, 0, wPreferences.icon_size, 
		    wPreferences.icon_size, 0, scr->depth, CopyFromParent, 
		    scr->w_visual, vmask, &attribs);
#endif
}


/*
 *----------------------------------------------------------------------
 * wScreenInit--
 * 	Initializes the window manager for the given screen and 
 * allocates a WScreen descriptor for it. Many resources are allocated
 * for the screen and the root window is setup appropriately.
 *
 * Returns:
 * 	The WScreen descriptor for the screen.
 * 
 * Side effects:
 * 	Many resources are allocated and the IconSize property is
 * set on the root window.
 *	The program can be aborted if some fatal error occurs.
 * 
 * TODO: User specifiable visual.
 *---------------------------------------------------------------------- 
 */
WScreen *
wScreenInit(int screen_number)
{
    WScreen *scr;
    XIconSize icon_size[1];
    RContextAttributes rattr;
    extern int wVisualID;
    WDDomain *domain;
    
    
    domain = wDefaultsInitDomain("WindowMaker");
    if (!domain->dictionary) {
	wWarning(_("could not read domain \"%s\" from defaults database"),
		 "WindowMaker");
    }
    
    /* read defaults that don't change until a restart */
    wReadStaticDefaults(domain ? domain->dictionary : NULL);

    /* swap mouse button functions */
    if (wPreferences.swap_buttons) {
	wLeftBtn = Button3;
	wRightBtn = Button1;
	wLeftBtnMask = Button3Mask;
	wRightBtnMask = Button1Mask;
    } else {
	wLeftBtn = Button1;
	wRightBtn = Button3;
	wLeftBtnMask = Button1Mask;
	wRightBtnMask = Button3Mask;
    }
    
    scr = wmalloc(sizeof(WScreen));
    memset(scr, 0, sizeof(WScreen));

    /* initialize globals */
    scr->screen = screen_number;
    scr->root_win = RootWindow(dpy, screen_number);
    scr->depth = DefaultDepth(dpy, screen_number);
    scr->colormap = DefaultColormap(dpy, screen_number);

    scr->scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_number));
    scr->scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_number));

    XSetErrorHandler((XErrorHandler)alreadyRunningError);
    XSelectInput(dpy, scr->root_win, EVENT_MASK);
    XSync(dpy, 0);
    XSetErrorHandler((XErrorHandler)NULL);

    XDefineCursor(dpy, scr->root_win, wCursor[WCUR_DEFAULT]);

    /* screen descriptor for raster graphic library */
    rattr.flags = RC_RenderMode | RC_ColorsPerChannel;
    rattr.render_mode = wPreferences.no_dithering?RM_MATCH:RM_DITHER;
    rattr.colors_per_channel = wPreferences.cmap_size;
    if (rattr.colors_per_channel<2)
	rattr.colors_per_channel = 2;

    if (wVisualID>=0) {
	rattr.flags |= RC_VisualID;
	rattr.visualid = wVisualID;
    }
    scr->rcontext = RCreateContext(dpy, screen_number, &rattr);
    if (!scr->rcontext) {
	wWarning(_("could not initialize graphics library context: %s"),
		 RErrorString);
	wAbort();
	exit(1);
    }

    scr->w_win = scr->rcontext->drawable;
    scr->w_visual = scr->rcontext->visual;
    scr->w_depth = scr->rcontext->depth;
    scr->w_colormap = scr->rcontext->cmap;

    scr->black_pixel = scr->rcontext->black;
    scr->white_pixel = scr->rcontext->white;

    
    scr->wmscreen = WMCreateScreen(dpy, screen_number, scr->rcontext);
    
    
    /* create GCs with default values */
    allocGCs(scr);
    
    /* read defaults */
    scr->dmain = domain;
    wReadDefaults(scr, domain->dictionary);

    /* create initial workspace */
    wWorkspaceNew(scr);

    /* init other domains */
    scr->droot_menu = wDefaultsInitDomain("WMRootMenu");
    if (!scr->droot_menu->dictionary) {
	wWarning(_("could not read domain \"%s\" from defaults database"),
		 "WMRootMenu");
    }

    scr->dwindow = wDefaultsInitDomain("WMWindowAttributes");
    if (!scr->dwindow->dictionary) {
	wWarning(_("could not read domain \"%s\" from defaults database"),
		 "WMWindowAttributes");
    }

    
    /* setup defaults file polling */
    wAddTimerHandler(3000, wDefaultsCheckDomains, scr);
    
    
    createInternalWindows(scr);

    /* create shared pixmaps */
    createPixmaps(scr);

    /* set icon sizes we can accept from clients */
    icon_size[0].min_width = 1;
    icon_size[0].min_height = 1;
    icon_size[0].max_width = wPreferences.icon_size;
    icon_size[0].max_height = wPreferences.icon_size;
    icon_size[0].width_inc = 1;
    icon_size[0].height_inc = 1;
    XSetIconSizes(dpy, scr->root_win, icon_size, 1);

    /* setup WindowMaker protocols property in the root window*/
    PropSetWMakerProtocols(scr->root_win);

    
    /* kluge to load menu configurations at startup */
    OpenRootMenu(scr, -10000, -10000, False);
    wMenuUnmap(scr->root_menu);
    
    
    return scr;
}


void
wScreenRestoreState(WScreen *scr)
{
    scr->session_state = PLGetProplistWithPath(wDefaultsPathForDomain("WMState"));

    wWorkspaceRestoreState(scr);
    
#ifdef DOCK
    if (!wPreferences.flags.nodock)
	scr->dock = wDockRestoreState(scr);
#endif
}


void
wScreenSaveState(WScreen *scr)
{
    WWorkspaceState wstate;
    WWindow *wwin;
    proplist_t path;

    wstate.flags = 0;
    if (scr->root_menu && scr->root_menu->flags.buttoned) {
	wstate.menu_x = scr->root_menu->frame_x;
	wstate.menu_y = scr->root_menu->frame_y;
	wstate.flags |= WSS_ROOTMENU;
    }

    if (scr->switch_menu && scr->switch_menu->flags.buttoned) {
	wstate.smenu_x = scr->switch_menu->frame_x;
	wstate.smenu_y = scr->switch_menu->frame_y;
	wstate.flags |= WSS_SWITCHMENU;
    }
    
     if (scr->workspace_menu && scr->workspace_menu->flags.buttoned) {
	wstate.wmenu_x = scr->workspace_menu->frame_x;
	wstate.wmenu_y = scr->workspace_menu->frame_y;
	wstate.flags |= WSS_WSMENU;
    }

/* 
 * Save current workspace, so can go back to it upon restart.
 */
    wstate.workspace = scr->current_workspace;


    XChangeProperty(dpy, scr->root_win, _XA_WINDOWMAKER_STATE,
                    _XA_WINDOWMAKER_STATE, 32, PropModeReplace,
                    (unsigned char *) &wstate, 
		    sizeof(WWorkspaceState)/sizeof(int));
    
    /* save state of windows */
    wwin = scr->focused_window;
    while (wwin) {
	wWindowSaveState(wwin);
	wwin = wwin->prev;
    }

    
    scr->session_state = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
    
#ifdef DOCK
    /* save dock state to file */
    if (scr->dock)
      wDockSaveState(scr);
#endif
    
    wWorkspaceSaveState(scr);

    path = PLMakeString(wDefaultsPathForDomain("WMState"));
    PLSetFilename(scr->session_state, path);
    PLSave(scr->session_state, YES);
    PLRelease(path);
}



int
wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height)
{
    int moved = 0;
    int tol_w, tol_h;
    
    if (width > 20)
	tol_w = width/2;
    else
	tol_w = 20;
    
    if (height > 20)
	tol_h = height/2;
    else
	tol_h = 20;

    if (*x+width < 10)
	*x = -tol_w, moved = 1;
    else if (*x >= scr->scr_width - 10)
	*x = scr->scr_width - tol_w - 1, moved = 1;

    if (*y < -height + 10)
	*y = -tol_w, moved = 1;
    else if (*y >= scr->scr_height - 10)
	*y = scr->scr_height - tol_h - 1, moved = 1;

    return moved;
}
