Menu

setSystemCursorEnabled problem

Peter
2014-02-28
2014-03-17
  • Peter

    Peter - 2014-02-28

    Hi,

    On WinXP the setSystemCursorEnabled function works as expected with the following code:

    WintabProvider wtp = AwtPenToolkit.getPenManager().getProvider(WintabProvider.class);
    wtp.setSystemCursorEnabled(false);
    

    But after I disconnect and plug back my Genius EasyPen i405X tablet to the same USB port the above code does not disable the cursor.

    What could be the problem?

    Thanks,
    Peter

     
  • Nicolas Carranza

    hi Peter,

    I ran the following test code on my system with Windows 7 and a wacom (Intuos) driver:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import jpen.event.*;
    import jpen.*;
    import jpen.provider.wintab.WintabProvider;
    import jpen.owner.multiAwt.AwtPenToolkit;
    
    public class Test {
    
        public static void main(String[] args) {
            final PenManager penManager=AwtPenToolkit.getPenManager();
            penManager.pen.setFirePenTockOnSwing(true);
            final JLabel penLabel=new JLabel();
            penLabel.setOpaque(true);
            penLabel.setBackground(Color.yellow);
            penLabel.setHorizontalAlignment(SwingConstants.CENTER);
            AwtPenToolkit.addPenListener(penLabel, new PenAdapter() {
                        @Override
                        public void penTock(long availableMillis) {
                            penLabel.setText("X: "+penManager.pen.getLevelValue(PLevel.Type.X));
                        }
                    }
                                                                    );
    
            final WintabProvider wintabProvider=AwtPenToolkit.getPenManager().getProvider(WintabProvider.class);
            if(wintabProvider==null) {
                System.out.println("This test is for the Windows OS.");
                return;
            }
            JPanel buttonsP=new JPanel();
            JButton onB=new JButton("On");
            onB.addActionListener(new ActionListener() {
                        //@Override
                        public void actionPerformed(ActionEvent ev) {
                            wintabProvider.setSystemCursorEnabled(true);
                        }
                    }
                                                     );
            buttonsP.add(onB);
            JButton offB=new JButton("Off");
            offB.addActionListener(new ActionListener() {
                        //@Override
                        public void actionPerformed(ActionEvent ev) {
                            wintabProvider.setSystemCursorEnabled(false);
                        }
                    }
                                                        );
            buttonsP.add(offB);
    
            JPanel panel=new JPanel(new BorderLayout());
            panel.add(penLabel);
            panel.add(buttonsP, BorderLayout.SOUTH);
    
            JFrame f=new JFrame("JPen - WintabProvider - cursor enabling test");
            f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            f.setMinimumSize(new Dimension(300, 300));
            f.add(panel);
            f.pack();
            f.setVisible(true);
        }
    
    }
    

    Having the tablet in pen mode (wacom properties setting, pen mode is absolute coordinate mapping), I press the "Off" button to disable the cursor and then disconnect/reconnect the tablet. After reconnection the cursor remains disabled and (if the cursor is on the yellow label and the JFrame is active) the tablet resumes sending data to the wintab provider (the x values change with subpixel precision on the yellow label)... everything seems to be working as expected. I guess that the problem is with the genius wintab driver (I don't have a genius tablet to test this on) :-S

    -Are you using the latest drivers available for your tablet?

    -Try changing the line of the test code:

    wintabProvider.setSystemCursorEnabled(false);
    

    to these two lines:

    wintabProvider.setSystemCursorEnabled(true);
    wintabProvider.setSystemCursorEnabled(false);
    

    and test pressing the "Off" button after reconnecting the tablet, does it disable the cursor?

    Cheers,
    Nicolas

     
  • Peter

    Peter - 2014-03-03

    Hi Nicolas,

    Thank you for the detailed example.

    I have the latest drivers installed.

    I tried the test code and it gave the same result as I experienced earlier: first time the "Off" button works but after reconnecting the genius tablet the system cursor became active and stays in enabled state despite pressing the "Off" button.
    Unfortunately the recommended double setSystemCursorEnabled with true and false state does not help.

    But...

    When I checked the basic functionality with debugging and the code executed line by line luckily I realized if I slowly stepping through the code the setSystemCursorEnabled works perfectly! After more research it looks like that inserting a sleep call "repairs" the fault.

    PenOwner penOwner = jpen.owner.ScreenPenOwner.getInstance();
    PenManager penManager = new PenManager(penOwner);
    Thread.sleep(2000); // 1st
    WintabProvider wtp = penManager.getProvider(WintabProvider.class);
    //Thread.sleep(2000); // 2nd
    wtp.setSystemCursorEnabled(false);
    

    It works either with the first or second sleep - but e.g 1000ms is not enough, with 2000ms it is ok. Very annoying...

    I'm afraid this is not an unfailing solution :\
    What do you think?

    Thank you!

    Peter

     
  • Nicolas Carranza

    hi Peter,
    do you have to introduce the sleep time and call the setSystemCursorEnabled(false) only once during the lifetime of the application (and the cursor remains disabled after many reconnections and everything works as expected) or do you have to invoke this code snippet (create a new PenManager, sleep, call setSystemCursorEnabled(false)) every time after reconnection for the cursor to be disabled?
    cheers!
    Nicolas

     
  • Peter

    Peter - 2014-03-05

    Hi Nicolas,

    Unfortunately it works only once, after reconnection the cursor become enabled and further setSystemCursorEnabled(false) call (or the true/false calls) does not work.

    By the way, is there method to reinitialize (or cleanup and recreate) an active penManager?

    Thank you!

    Regards,
    Peter

     
  • Nicolas Carranza

    hi Peter, a way to reinitialize the pen event source could be recreating the PenManager. You can play with the following:

    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    import jpen.*;
    import jpen.event.*;
    import jpen.owner.ScreenPenOwner;
    import jpen.provider.wintab.WintabProvider;
    
    abstract class ScreenPenManager {
        private PenListener penListener;
        private PenManager penManager;
    
        {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                        @Override
                        public void run() {
                            // wacom wintab implementation seems to associate wintab context to the root window, so it is polite to do this call to avoid leaving the system cursor disabled
                            setWintabSystemCursorEnabled(true);
                        }
                    }
                                                                                    );
        }
    
        synchronized void setPenListener(PenListener penListener) {
            if(this.penListener!=null && penManager!=null)
                penManager.pen.removeListener(this.penListener);
            this.penListener = penListener;
            if(penManager==null)
                createPenManager();
            if(penListener!=null)
                penManager.pen.addListener(penListener);
        }
    
        private void createPenManager() {
            penManager=new PenManager(ScreenPenOwner.getInstance());
            initialize(penManager);
        }
    
        protected abstract void initialize(PenManager penManager);
    
        synchronized void recreatePenManager() {
            // PenManager recreation procedure is platform dependent and there is no need to do it if we are not running Windows.
            if(!System.getProperty("os.name").toLowerCase().contains("windows"))
                return;
            PenListener penListener=this.penListener;
            setPenListener(null);
            createPenManager();
            setPenListener(penListener);
        }
    
        synchronized PenManager getPenManager() {
            return penManager;
        }
    
        synchronized void setWintabSystemCursorEnabled(boolean enabled) {
            WintabProvider wintabProvider=getPenManager().getProvider(WintabProvider.class);
            if(wintabProvider!=null) {
                // sleep?
                wintabProvider.setSystemCursorEnabled(enabled);
            }
        }
    }
    
    public class Test2 {
    
        public static void main(String[] args) {
            final ScreenPenManager screenPenManager=new ScreenPenManager() {
                        @Override
                        protected void initialize(PenManager penManager) {
                            setWintabSystemCursorEnabled(false);
                            penManager.pen.setFirePenTockOnSwing(true);
                        }
                    };
            final JLabel penLabel=new JLabel();
            penLabel.setOpaque(true);
            penLabel.setBackground(Color.yellow);
            penLabel.setHorizontalAlignment(SwingConstants.CENTER);
            screenPenManager.setPenListener(new PenAdapter() {
                        @Override
                        public void penTock(long availableMillis) {
                            penLabel.setText("X: "+screenPenManager.getPenManager().pen.getLevelValue(PLevel.Type.X));
                        }
                    }
                                                                         );
    
            JPanel buttonsP=new JPanel();
            JButton onB=new JButton("On");
            onB.setMnemonic('n');
            onB.addActionListener(new ActionListener() {
                        //@Override
                        public void actionPerformed(ActionEvent ev) {
                            screenPenManager.setWintabSystemCursorEnabled(true);
                        }
                    }
                                                     );
            buttonsP.add(onB);
            JButton offB=new JButton("Off");
            offB.setMnemonic('f');
            offB.addActionListener(new ActionListener() {
                        //@Override
                        public void actionPerformed(ActionEvent ev) {
                            screenPenManager.setWintabSystemCursorEnabled(false);
                        }
                    }
                                                        );
            buttonsP.add(offB);
            JButton recreateB=new JButton("Recreate PenManager");
            recreateB.setMnemonic('R');
            recreateB.addActionListener(new ActionListener() {
                        //@Override
                        public void actionPerformed(ActionEvent ev) {
                            screenPenManager.recreatePenManager();
                        }
                    }
                                                                 );
            buttonsP.add(recreateB);
    
            JPanel panel=new JPanel(new BorderLayout());
            panel.add(penLabel);
            panel.add(buttonsP, BorderLayout.SOUTH);
    
            JFrame f=new JFrame("JPen - WintabProvider - cursor enabling test");
            f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            f.setMinimumSize(new Dimension(300, 300));
            f.add(panel);
            f.pack();
            f.setVisible(true);
        }
    }
    

    It works as expected on my system (wacom wintab implementation)... pressing "Recreate PenManager" has the same effect as pressing the "Off" button which disables the system cursor.

    The right way to solve this bug would be to forward it to the genius developer team (no pun intended ;-)... but I don't want to do it myself because it requires a test case with better isolation of the problem and I don't have the hardware (genius tablet) to prepare it. I opened a bug report on our bug database here https://sourceforge.net/p/jpen/bugs/21/ .

    Cheers!
    Nicolas

     

    Last edit: Nicolas Carranza 2014-03-06
  • Peter

    Peter - 2014-03-17

    Hi Nicolas,

    Thank you very much for the test code. Disabling the cursor works only after restarting the test app, even with the thread sleep inserted. I experienced similar behavior earlier, this is why i asked the correct initialization method.

    I'm trying to contact with genius tech support.

    Regards,
    Peter