Drawing the Mouse Cursor

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

Drawing the Mouse Cursor

Post by onlyonemac »

Hi!

I've been designing pretty much everything about my operating system from scratch, without reading any tutorials beyond that needed to figure out hardware I/O, but now I'm stuck with something, and I'm wondering how others do this.

Essentially my problem is to do with drawing the mouse cursor. I can draw the cursor, but when it comes to undrawing it before moving it I don't know how to determine what's underneath it. I thought of keeping a small buffer the size of the cursor containing the obscured pixels, but that was going to get difficult if the pixels under the cursor are changed. Short of keeping a separate buffer for every window (which I know can be avoided since X11 without a composting manager can do mouse cursors), I can't seem to understand how to do this.

Any ideas?

Thanks,

onlyonemac
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Drawing the Mouse Cursor

Post by alexfru »

I made my mouse pointer out of multiple windows, each of which being just one or just a few pixels large. And then I used the existing window-handling code to draw and redraw the pointer. These tiny mouse pointer windows are always on the top of all other windows and this is reflected in the data structures maintaining the z-order of all the windows.
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: Drawing the Mouse Cursor

Post by max »

Im currently writing my window manager too, so Im facing the same issues :P

I cant tell you if its all correct, but this is how I do it:
The desktop and all windows have their own buffer. When the screen is painted for the first time, all the window buffers are copied to the desktop buffer, which is the copied to the graphics frame buffer. When something changes somewhere, the area on the desktop or the area on the corresponding window that has changed is marked as "dirty". Then when the screen is painted again, only the dirty areas are copied to the desktop buffer again, and then the sum area of all dirty areas on the desktop buffer is copied to the graphics frame buffer. A cursor is then treated as any other window.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Drawing the Mouse Cursor

Post by sortie »

Note that if you have hardware support, some video cards allow a transparent small overlay on the framebuffer. You can put the mouse pointer here and simply move that overlay around - this will move the mouse around very cheaply without needing to redraw anything.

The modern solution is just to render the mouse like another partially transparent window, where you just redraw the damage rects when stuff moves - the window manager remembers the contents of each window so it can redraw without roundtrips. Your alternate method of remembering what you obscure can work, too - if paired with proper cache invalidation, when a window redraws while the mouse hovers above it, for instance.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: Drawing the Mouse Cursor

Post by Gigasoft »

Treating the cursor as a window (or even worse, multiple windows) sounds slow. I keep a copy of the pixels that are underneath the cursor. When a window is updated or moved and it overlaps with the cursor, the cursor is automatically hidden.
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Drawing the Mouse Cursor

Post by alexfru »

Gigasoft wrote:Treating the cursor as a window (or even worse, multiple windows) sounds slow. I keep a copy of the pixels that are underneath the cursor. When a window is updated or moved and it overlaps with the cursor, the cursor is automatically hidden.
So, you prefer to steal it from the user? :)

Slow or not really depends on how you implement window (re)drawing. If you redraw too much, enough to be noticeable when the mouse moves around, you have a real problem in the plain sight, because then if you drag a quarter-screen-sized window, you'll see what is really slow. If you redraw just a hundred of pixels, it's not a big deal, whether or not they represent minuscule windows or just a single small one.
User avatar
AndrewAPrice
Member
Member
Posts: 2303
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: Drawing the Mouse Cursor

Post by AndrewAPrice »

Either double buffer or redraw the windows (the windows themselves may double buffer to avoid flickering updates). Do you double buffer your window manager when windows overlap? If so, just redraw the buffer on vsync then draw your mouse.

Alternatively, a fast single buffering approach may be to just to invert the pixels where the mouse is, and when you move your cursor remember to invert the old pixels back.
My OS is Perception.
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: Drawing the Mouse Cursor

Post by Shaun »

MessiahAndrw wrote: Alternatively, a fast single buffering approach may be to just to invert the pixels where the mouse is, and when you move your cursor remember to invert the old pixels back.
i take this approach actually.it's cool, fast and awesome!
remember this :A xor B xor B=A xor 0=A and you will see your mouse color changing when you do a cursor moving.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Drawing the Mouse Cursor

Post by Brendan »

Hi,
Shaun wrote:
MessiahAndrw wrote: Alternatively, a fast single buffering approach may be to just to invert the pixels where the mouse is, and when you move your cursor remember to invert the old pixels back.
i take this approach actually.it's cool, fast and awesome!
remember this :A xor B xor B=A xor 0=A and you will see your mouse color changing when you do a cursor moving.
Minecraft does this when drawing cross-hairs in the middle of the screen. If you're looking at something grey, then the underlying grey gets inverted to grey and the cross-hairs are invisible (!).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: Drawing the Mouse Cursor

Post by Shaun »

Brendan wrote:Hi,
Shaun wrote:
MessiahAndrw wrote: Alternatively, a fast single buffering approach may be to just to invert the pixels where the mouse is, and when you move your cursor remember to invert the old pixels back.
i take this approach actually.it's cool, fast and awesome!
remember this :A xor B xor B=A xor 0=A and you will see your mouse color changing when you do a cursor moving.
Minecraft does this when drawing cross-hairs in the middle of the screen. If you're looking at something grey, then the underlying grey gets inverted to grey and the cross-hairs are invisible (!).


Cheers,

Brendan

here is a video of my os gfx test show.
take a little bit care of the mouse color and it 's changing when you do a moving.
https://www.youtube.com/watch?v=Y95iuVXSAMk


http://v.youku.com/v_show/id_XNzE2OTA4NDg0.html
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

Re: Drawing the Mouse Cursor

Post by onlyonemac »

I've got a single buffer for each window, so currently I'm just using that to redraw the exposed window areas.
MessiahAndrw wrote:Alternatively, a fast single buffering approach may be to just to invert the pixels where the mouse is, and when you move your cursor remember to invert the old pixels back.
As explained in the first post, that's no good if the pixels under the cursor get changed.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Drawing the Mouse Cursor

Post by Combuster »

It's good enough to "undo" the cursor if other drawing happens to intersect it, no?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Drawing the Mouse Cursor

Post by Love4Boobies »

I'm not sure what window managers should have to do with drawing the cursor. It seems to me that the best place for this functionality is the video driver. If the hardware supports accelerated cursors, good. If not, it can just provide a software implementation (using one of the techniques described in this thread, perhaps). This will result in a uniform interface and modular implementations.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
mallard
Member
Member
Posts: 280
Joined: Tue May 13, 2014 3:02 am
Location: Private, UK

Re: Drawing the Mouse Cursor

Post by mallard »

Old versions of Windows (and possibly modern versions under certain circumstances) used to do something like this:
  • Before drawing the cursor, save the pixels from the cursor's bounding rectangle in an off-screen buffer.
  • Draw the cursor.
  • When the cursor moves, blit the saved pixels back into place and repeat the process at the new location.
  • If an application draws into the space occupied by the cursor, temporarily hide the cursor (by blitting the saved pixels), do the drawing operation and then restore the cursor.
This results in a characteristic "flickering" cursor when it's placed over the top of a frequently updated part of the screen (e.g. a video or animation), but was, for the most part "good enough" at the time. Of course, even the earliest 2D accelerated graphics cards supported a hardware cursor, so this really only happens if you're using something like standard VGA or VESA.
Image
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: Drawing the Mouse Cursor

Post by Love4Boobies »

The only two sane options are really:
  • Relying on the back buffer to keep track of the background.
  • Keeping and updating a small buffer describing the background.
Anything else will introduce some flickering.

The XOR mask thing, as described above, is just a trick to overlap the front and background buffers in order to save the bit of memory required for storing the background separately, at the expense of performance and artistic options. It has nothing to do with the problem of updating the background (you still need to hide the cursor or to update the mask, which are basically the two general approaches, as discussed in this thread). However, the invisibility problem referenced by Brendan applies only if the mask has a uniform "color," which would be a problem for any cursor.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
Post Reply