15
\$\begingroup\$

You know those Windows boxes where you can only do one thing?

Windows Error Box: Proceeding will delete the contents of your hard drive. What do you want to do? <Proceed> <Delete>

Let's take this to the next level!

Challenge

Make a dialog box with a button that follows your cursor everywhere!

Specs

No input may be taken. There may be output to either STDOUT or STDERR. You must open a window with one button (no text is necessary, but text may be contained in either the window title, the dialog box, or the button). The button must be clickable, and it must always follow under your cursor so that you can only click it. Upon clicking, it can do anything you want, but please do not make it crash a computer because I will be testing this... The dialog box must stay open for as long as the button is not pressed, but it does not need to close when the button is closed.

Assumptions that you can make

  • You may assume that the cursor will stay within the drawing canvas.
  • You may assume that the window will stay in focus, but you must not put the window out of focus as long as the button is not pressed.

Example Pseudocode

Here's some example pseudocode:

Open Dialog Box
Add Button to Dialog Box at position X, Y
WHILE True:
    SET Dialog Box to CursorX - X, CursorY - Y

Test Cases cannot be provided for this challenge

This is a code-golf challenge, so the shortest valid submission by March 14th (Pi Day) wins!

\$\endgroup\$
2
  • \$\begingroup\$ If cursor follows me everywhere, I would escape by pressing the power button \$\endgroup\$
    – Wasif
    Jun 2, 2021 at 6:05
  • 1
    \$\begingroup\$ @Wasif It's too late; the cursor has already escaped out of the virtual world. Watch out behind you. \$\endgroup\$
    – hyper-neutrino
    Jun 2, 2021 at 6:05

10 Answers 10

9
\$\begingroup\$

MATLAB, 86 63 bytes

set(warndlg,'WindowButtonM',@(s,e)movegui(get(0,'Po')-[99,20]))

This solution takes advantage of MATLAB's (typically annoying) ability to use partial property names as long as the part that is provided is unique to only the property of interest.

This solution uses the builtin warndlg to create a warning dialog with an "OK" button. This function returns a figure handle which we can then use to set the WindowButtonMotionFcn callback (using the short name 'WindowButtonM').

The callback that is evaluated any time the cursor is moved within the window gets the current position of the cursor (using the PointerLocation property of the root graphics object, using it's short name 'Po'). We then update the Position of the figure using movegui and specifying the new location of the figure after applying an offset of [99, 20] so that the cursor is placed on the button.

When the button is finally clicked, the figure is deleted and all callbacks are automatically released.

enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ A couple of issues on Windows R2014a. You can stop the dialog box from following by: 1. Moving your mouse (along with the dialog) box to the taskbar (my taskbar is on the right side of the screen) and the dialog box will stop following the mouse; 2. Moving your mouse fast enough such that the mouse is outside the dialog box at any frame, at which point the box will stop following the mouse. The style of the dialog box is also apparently dependent on something else... with the current code, my mouse barely misses the OK button, and I have to change 99 to 120 to work. Anyway, good work! \$\endgroup\$
    – Frenzy Li
    Feb 27, 2017 at 8:11
  • \$\begingroup\$ This is what I see from my perspective. My mouse is somewhere near that red crosshair. \$\endgroup\$
    – Frenzy Li
    Feb 27, 2017 at 8:13
4
\$\begingroup\$

C# (Windows Form Application), 200 114 bytes

void F(){var p=Cursor.Position;MouseMove+=(r,t)=>{Controls.Add(new Button());Location=new Point(p.X-30,p.Y-40);};}

Un-Golfed

void F()
{
     Controls.Add(new Button());

     MouseMove += (r, t) =>
     {
        var p = Cursor.Position;
        Location = new Point(p.X - 30, p.Y - 40);
     };
}

Old 200-byte solution:

public void F(){var t=this;var b=new Button();b.Click+=delegate{t.Close();};t.Controls.Add(b);t.Show();for(;;){Application.DoEvents();t.Location=new Point(Cursor.Position.X-30,Cursor.Position.Y-40);}}

Un-Golfed

    public void F()
    {
        var t = this;
        var b = new Button();

        b.Click += delegate
        {
            t.Close();
        };

        t.Controls.Add(b);
        t.Show();

        for (;;)
        {
            Application.DoEvents();
            t.Location = new Point(Cursor.Position.X - 30, Cursor.Position.Y - 40);
        }
    }

enter image description here

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Wait.... so in C#, you can add an event listener by doing Event += listener? That's awesome :-) \$\endgroup\$ Feb 24, 2017 at 22:56
  • \$\begingroup\$ @ETHproductions Could probably do that in C++ too if you overloaded the + operator. Still very succinct. \$\endgroup\$ Feb 26, 2017 at 1:01
1
\$\begingroup\$

AutoHotkey, 122 115 bytes

MsgBox
WinWait,%A_ScriptName%
Loop{
MouseGetPos,x,y
WinGetPos,a,b
ControlGetPos,c,d,,,Button1
WinMove,x+a-c,y+b-d
}

Demo

\$\endgroup\$
0
1
\$\begingroup\$

Java 7, 294 289 286 264 220 bytes

import java.awt.*;public class B extends java.applet.Applet{Button b;public B(){add(b=new Button());}public void paint(Graphics g){Point p=MouseInfo.getPointerInfo().getLocation();b.setLocation(p.x-9,p.y-65);repaint();}}

-22 bytes thanks to MouseInfo (stolen from Zavada) I don't like the awt libraries >.>

I shaved off 44 bytes by removing the main method here. The main method isn't needed if this is launched as an applet. This can be achieved via eclipse's "Run As Java Applet" or by disabling the security manager and using appletviewer, which comes with the JDK (unless you're still able to view applets in web browsers. I don't think chrome allows this).

popup

\$\endgroup\$
3
  • \$\begingroup\$ You can save 24 bytes by removing import java.awt.event.*; \$\endgroup\$
    – Zavada
    Feb 24, 2017 at 22:48
  • \$\begingroup\$ @Zavada The * wildcard does not recursively import subpackages. I need java.awt.event for the MouseAdapter and MouseEvent \$\endgroup\$
    – Poke
    Feb 24, 2017 at 23:32
  • \$\begingroup\$ Apologies, I had a total brainfart! \$\endgroup\$
    – Zavada
    Feb 25, 2017 at 0:25
1
\$\begingroup\$

Java, 172 199 235 Bytes

Golfed:

import java.awt.*;interface D{static void main(String[]z){new javax.swing.JDialog(){{setSize(9,99);setVisible(1>0);add(new Button());a();}void a(){for(Point p;;p=MouseInfo.getPointerInfo().getLocation(),setLocation(p.x-9,p.y-70));}};}}

Ungolfed:

import java.awt.*;
interface D{
    static void main(String[]z){
        new javax.swing.JDialog(){
            {
                setSize(9,99);
                setVisible(1>0);
                add(new Button());
                a();
            }
            void a(){
                
                for(;;) {
                    Point p = MouseInfo.getPointerInfo().getLocation();
                    setLocation(p.x-9,p.y-70);
                }
            }
        };
        
    }
}

Explanation: I use double brace initialization on my declaration of a new JDialog. This saved bytes by excluding the extension of JDialog (allowing me to save bytes excluding public from main). Inside JDialog's anonymous subclass I make it visible (using 1>0 instead of true) and call a(), which is necessary because the initalizer has a compile-time error if the loop were sat in it normally. I opted to use MouseInfo rather than all the excess code associated with adding a mouse listener.

Edit: Had to increase count by 27 to add add(new java.awt.Button());. I thought JDialogs had an implied button by technicality, but I seem to be wrong.

Edit 2: Had to add setSize and offset mouse location to make the button clickable.

Dialog

\$\endgroup\$
2
  • \$\begingroup\$ I didn't know/remember MouseInfo was a thing. This is a neat answer. \$\endgroup\$
    – Poke
    Feb 26, 2017 at 1:03
  • 1
    \$\begingroup\$ @Poke Thanks. I saw your answer using applets, and I have an unreasonable hatred for applets, so I felt it would be cute to do in swing. Your answer is nice though :) \$\endgroup\$
    – Zavada
    Feb 27, 2017 at 16:24
0
\$\begingroup\$

Modified Processing Js 102 108 bytes

draw=function(){background(0);rect(mouseX,mouseY,9,9);rect(mouseX,mouseY,4,4);if(mouseIsPressed){fill(9);}};

Try it online! Just updated my link!

It just draws a rectangle that follows your mouse and a smaller rectangle inside of it that you click and it turns red. It works but is not amazing. This version if very strict on braces and all of that :(

\$\endgroup\$
6
  • \$\begingroup\$ You can remove the braces around fill \$\endgroup\$
    – user41805
    Feb 23, 2017 at 16:40
  • \$\begingroup\$ @KritixiLithos I actually can't :( \$\endgroup\$ Feb 23, 2017 at 16:41
  • \$\begingroup\$ It is a strictly type language version \$\endgroup\$ Feb 23, 2017 at 16:44
  • \$\begingroup\$ You could use another type of Processing to save bytes then \$\endgroup\$
    – user41805
    Feb 23, 2017 at 16:47
  • \$\begingroup\$ @KritixiLithos actually then I would also have to set up a screen size and that would add bytes. (Side note I just got kicked from chat for "inappropriate content any idea why? It was a bot too. chat.stackexchange.com/messages/35631789/history was why \$\endgroup\$ Feb 23, 2017 at 16:49
0
\$\begingroup\$

Clojure, 525 bytes

(ns d(:require[quil.core :as q][quil.middleware :as m]))(def w 500)(def h 200)(def t 30)(def n 200)(def m 100)(q/defsketch d :size[999 999]:setup(fn[](q/stroke 0 0 0)(q/text-font(q/create-font""(* t 1.3))){:x 0 :y 0}):draw(fn[{x :x y :y}](let[r q/rect f q/fill o(- x(/ w 2))p(- y (/ h 2))](q/background 99 99 99)(f 0 0 255)(r o p w h)(f 200 200 200)(r o(+ p t)w(- h t))(f 255 0 0)(r(-(+ o w)t)p t t)(f 255 255 255)(q/text"X"(- (+ o w) t)(+ p t))(r(- x(/ n 2))(- y (/ m 2))n m))):mouse-moved(fn[_ e]e):middleware[m/fun-mode])

Does not create a genuine Windows dialog. Instead, it builds a fake one, and creates a dummy (non-functioning) button in the middle.

This was allowed by the OP in the comments.

Uses the Quil library.

(ns bits.golf.following-dialog
  (:require [quil.core :as q]
            [quil.middleware :as m]))

(def width 500)
(def height 200)

(def top-bar-height 30)

(def b-width 200)
(def b-height 100)

(defn -main []
  (q/defsketch d
    :size [999 999]
    :setup (fn []
             ; Set the border color
             (q/stroke 0 0 0)

             ; Set the font size
             (q/text-font (q/create-font "" (* top-bar-height 1.3)))

             ; The initial state
             {:x 0 :y 0})

    :draw (fn [{x :x y :y}]
            (let [r q/rect ; Shortcut functions for brevity
                  f q/fill

                  ; The top-left coordinates of the window
                  window-x  (- x (/ width 2))
                  window-y (- y (/ height 2))]

              ; Wipe the previous screen
              (q/background 99 99 99)

              ; Blue top bar
              (f 0 0 255)
              (r window-x
                 window-y
                 width height)

              ; Grey window background
              (f 200 200 200)
              (r window-x
                 (+ window-y top-bar-height)
                 width (- height top-bar-height))

              ; Red top right "button"
              (f 255 0 0)
              (r (- (+ window-x width)
                    top-bar-height)
                 window-y
                 top-bar-height top-bar-height)

              ; The X
              (f 255 255 255)
              (q/text "X" (- (+ window-x width) top-bar-height)
                          (+ window-y top-bar-height))

              ; The main "button"
              (r (- x (/ b-width 2))
                 (- y (/ b-height 2))
                 b-width
                 b-height)))

    ; When the mouse is moved, set the current state to the event object, which
    ;  conveniently has :x and :y properties
    :mouse-moved (fn [_ e] e)
               
    ; Needed for ease of state management. May try to factor out.
    :middleware [m/fun-mode]))

Fake Dialog

\$\endgroup\$
0
0
\$\begingroup\$

Javascript (ES6) + HTML + CSS, 139 bytes

HTML:

<d id=d><button>X

CSS:

d{background:red;padding:9px;position:absolute

Javascript:

onmousemove=e=>{with(d.style){top=e.clientY-20+'px';left=e.clientX-20+'px'}}

Since you can't position alert dialogs, I made my custom super fancy dialog in HTML. The javascript registers an event handler on the window object and sets the position to the coordinates of the event.

Try it online: https://jsfiddle.net/1yohswje/

\$\endgroup\$
0
0
\$\begingroup\$

Pug/Slim + CSS/SCSS/LESS/Stylus + ES6 Javascript (98 Bytes)

Try it online!

Pug (10 UTF-8 Bytes)

button#a X

Stylus (18 UTF-8 Bytes)

#a{position:fixed}

JS (70 UTF-8 Bytes)

onmousemove=e=>{with(a.style){top=e.clientY+'px';left=e.clientX+'px'}}

Decompiled, Ungolfed and explained Snippet:

document.addEventListener('mousemove', function(e) {
  // Get element with an id of "id"
  var el = document.getElementById("id");
  // Set the vertical position
  el.style.top = e.clientY + 'px';
  // Set the horizontal position
  el.style.left = e.clientX + 'px';
})
/* Get element with an id of "id" */

#id {
  /* Position it relative to the viewport*/
  position: fixed;
}
<!-- A basic HTML button with an ID of "id" -->
<button id='id'>
  X
</button>

\$\endgroup\$
0
\$\begingroup\$

Mathematica 226 Bytes

The mouse position relative to the screen is tracked by the front end and the window position of the dialog notebook is moved whenever the mouse moves. Pretty simple, but the commands are very lengthy in terms of letters, as often the case with Mathematica. Clicking OK will close the dialog.

{s,d,w}={SetOptions,Dynamic,WindowMargins->m};With[{p=d@MousePosition["ScreenAbsolute"]},
m=d@{{p[[1]]-50,0},{0,p[[2]]-35}}];s[$FrontEndSession,FrontEndEventActions->{"MouseMoved":>s[a,w]}];a=CreateDialog[{DefaultButton[]},w];

P.S. When you're done testing, run this to remove the front end option.

SetOptions[$FrontEndSession,FrontEndEventActions->None]

screen animation

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.