Page 1 of 1
Drawing the Mouse Cursor
Posted: Fri May 23, 2014 1:02 pm
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
Re: Drawing the Mouse Cursor
Posted: Fri May 23, 2014 1:18 pm
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.
Re: Drawing the Mouse Cursor
Posted: Fri May 23, 2014 1:37 pm
by max
Im currently writing my window manager too, so Im facing the same issues
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.
Re: Drawing the Mouse Cursor
Posted: Fri May 23, 2014 2:58 pm
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.
Re: Drawing the Mouse Cursor
Posted: Fri May 23, 2014 11:38 pm
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.
Re: Drawing the Mouse Cursor
Posted: Sat May 24, 2014 12:30 am
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.
Re: Drawing the Mouse Cursor
Posted: Sat May 24, 2014 6:08 pm
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.
Re: Drawing the Mouse Cursor
Posted: Sat May 24, 2014 9:04 pm
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.
Re: Drawing the Mouse Cursor
Posted: Sat May 24, 2014 9:24 pm
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
Re: Drawing the Mouse Cursor
Posted: Sun May 25, 2014 3:28 am
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
Re: Drawing the Mouse Cursor
Posted: Sun May 25, 2014 10:47 am
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.
Re: Drawing the Mouse Cursor
Posted: Sun May 25, 2014 11:51 am
by Combuster
It's good enough to "undo" the cursor if other drawing happens to intersect it, no?
Re: Drawing the Mouse Cursor
Posted: Sun May 25, 2014 2:41 pm
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.
Re: Drawing the Mouse Cursor
Posted: Sun May 25, 2014 5:59 pm
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.
Re: Drawing the Mouse Cursor
Posted: Sun May 25, 2014 10:14 pm
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.