#!/usr/bin/python

# be_busy.py
#       --copyright--                   Copyright 2010 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       October 24, 2009        bar
#       November 18, 2009       bar     attempt to not leak memory
#       December 25, 2009       bar     don't beep unless told to
#       January 18, 2010        bar     -q option
#       January 20, 2010        bar     try a windows kludge
#       January 21, 2010        bar     keep putting xlib code in (locked desktop goes to screen saver)
#       March 4, 2010           bar     cmd line param for display name
#       November 29, 2011       bar     pyflake cleanup
#       --eodstamps--
##      \file
#
#
#       Be busy on an X Windows system
#
#

try :
    import  Xlib.display
    import  Xlib.X
    import  Xlib.ext.xtest  as      xtest
except ImportError :
    Xlib    = None


import      tzlib
import      tz_windows_stuff



recent_down_when    = tzlib.elapsed_time()
recent_x            = -1
recent_y            = -1
delta               = -1


def get_mouse_xy(ds = None) :
    if  Xlib :
        nds = ds
        if  not nds :
            ds  = Xlib.display.Display()
        sd  = ds.screen().root.query_pointer()._data

        if  not nds :
            del(ds)

        return(sd['root_x'], sd['root_y'])

    return(None, None)


def mouse_goto(x, y, ds = None) :
    if  Xlib :
        nds = ds
        if  not nds :
            ds  = Xlib.display.Display()
        rt  = ds.screen().root
        Xlib.WarpPointer(ds, 0, rt, 0, 0, 0, x, y)
        if  not nds :
            del(ds)

        return(True)

    return(False)


def mouse_nudge(x, y, ds = None) :
    if  Xlib :
        nds = ds
        if  not nds :
            ds  = Xlib.display.Display()
        rt  = ds.screen().root
        Xlib.WarpPointer(ds, rt, 0, 0, 0, 0, x, y)
        if  not nds :
            del(ds)

        return(True)

    return(False)



try :
    from ctypes import cdll
except ImportError  :
    cdll            = None

def move_mouse(x, y) :
    if  cdll :
        dll     = cdll.LoadLibrary('libX11.so')
        d       = dll.XOpenDisplay(None)
        root    = dll.XDefaultRootWindow(d)
        dll.XWarpPointer(d, None, root, 0, 0, 0, 0, x, y)
        dll.XCloseDisplay(d)
        return(True)
    return(False)


def nudge_mouse(x, y) :
    if  cdll :
        dll     = cdll.LoadLibrary('libX11.so')
        d       = dll.XOpenDisplay(None)
        root    = dll.XDefaultRootWindow(d)
        dll.XWarpPointer(d, root, None, 0, 0, 0, 0, x, y)
        dll.XCloseDisplay(d)
        return(True)
    return(False)




def track_activity() :
    """ This is silly. There are better ways to do this. """

    global      recent_down_when, recent_x, recent_y

    if  not Xlib :
        if  tz_windows_stuff :
            m   = tz_windows_stuff.a_mouse()
            lup = m.get_mouse_left_up()
            if not lup :
                recent_down_when    = tzlib.elapsed_time()
            pass
        pass
    else    :
        ( x, y )    = get_mouse_xy()
        if (x != recent_x)  or  (y != recent_y) :
            recent_x                = x
            recent_y                = y
            recent_down_when        = tzlib.elapsed_time()
        pass
    pass



def be_busy(display = None, quiet = True) :
    global  delta

    track_activity()

    if  not Xlib :
        if  tz_windows_stuff :
            if  tzlib.elapsed_time() - recent_down_when >= 60 :
                tz_windows_stuff.a_mouse().left_release()

            return(True)

        return(False)

    nds = None
    if  not display :
        nds = Xlib.display.Display()

    ds  = display or nds

    ds.force_screen_saver(Xlib.X.ScreenSaverReset)                  # note: fire up the screen saver with X.ScreenSaverActive
    if  not quiet :
        ds.bell(50)

    if  tzlib.elapsed_time() - recent_down_when >= 10 :
        ( x, y )    = get_mouse_xy(display)

        # print "being busy", x, y, tzlib.elapsed_time()

        nudge_mouse(delta, 0)
        delta       = -delta
        nudge_mouse(delta, 0)

        # recent_x  = x + delta
        # xtest.fake_input(ds, Xlib.X.MotionNotify, x = recent_x, y = y)

        ds.flush()
        # ds.sync()
        # xtest.fake_input(ds, Xlib.X.MotionNotify, x = x, y = y)
        # ds.flush()

    ds.sync()

    if  nds :
        del(nds)

    return(True)


if __name__ == '__main__' :
    import  sys
    import  time

    import  TZCommandLineAtFile
    import  tz_parse_time


    program_name    = sys.argv.pop(0)
    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)

    quiet           = False
    display_name    = None


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--quiet", "-q" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        quiet       = True


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--display", "-d" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        display_name    = sys.argv.pop(oi)


    how_long        = 0
    if  sys.argv :
        ts          = sys.argv.pop(0)
        how_long    = tz_parse_time.parse_time_zone(ts)
        if  how_long == None :
            print "I don't understand %s as a time. Try hh:mm:ss!" % ts
            sys.exit(101)
        if  how_long < 0 :
            print "Keeping the screen saver off forever..."
        else        :
            print "Keeping the screen saver off for %u seconds..." % int(how_long)
        pass

    ds          = None
    if  Xlib    :
        ds      = Xlib.display.Display(display_name)

    st          = tzlib.elapsed_time()
    while True  :
        if  not be_busy(ds, quiet = quiet) :
            break

        if  (how_long >= 0) and (tzlib.elapsed_time() - st >= how_long) :
            break
        time.sleep(1)

    pass

#
#
#
# eof

