Opened 6 years ago

Last modified 2 years ago

#9457 assigned enhancement

API for Obtaining Cursor Shape Bitmap and Change Notification

Reported by: AGMS Owned by: nobody
Priority: normal Milestone: R1
Component: Servers/app_server Version: R1/Development
Keywords: cursor, vnc Cc: agmsmith@…
Blocked By: Blocking:
Has a Patch: no Platform: All


While updating the BeOS VNC server for Haiku, it occurs to me that it would be nice to have the Haiku specific cursor (hand shape, pointer arrow, insertion marker, etc) displayed at the VNC client side of things. VNC has an API for transmitting the cursor, and the client software does change the system cursor there to match the new bitmap. All we need to have is the bitmap from Haiku and some sort of notification of when it has changed.

Since we're using a BDirectWindow to do the screen scraping, perhaps the API could be added there (that also avoids the problem of deciding which workspace it is on, etc). Though I think someone with more knowledge should decide where it should go. The API could be something like this:

  • GetCursorBitmap - reads the current cursor bitmap, includes alpha transparency. Need the pixel format too, if it's not a simple RGBA 32 bit pixel, and maybe worry about endianness too.
  • GetCursorSerialNumber - gets the count of the number of times the cursor has been changed. The idea is that the VNC server will periodically call this and if the number has changed, get the new cursor bitmap and transmit it over the network to the client.
  • IsCursorDrawn - returns TRUE if the cursor is being drawn into the screen video memory. FALSE if it is a separate video hardware cursor.

If the hardware cursor is off or not implemented, then it does seem to work, since Haiku writes the cursor shape into the screen's bitmap and VNC picks that up. If the hardware cursor is operational, then the user doesn't see anything and the VNC client currently substitutes a black dot or some other fixed graphic to show where the mouse is.

By the way, one other obvious but actually not useful VNC optimisation would be to have the app_server report all the dirty areas of the screen, so VNC can know which parts need updating over the network. It currently scans the whole screen to find the changed parts, which can be slow. On the other hand, the current method is more responsive since it scans in slices so each update will be small enough to keep feedback (mouse movement) fast. So using the dirty areas would actually make things feel slower for the user!

Attachments (1)

ScreenchangesAPI.rtf (59.5 KB) - added by jackburton 6 years ago.
Screen changes api proposal draft (rtf)

Download all attachments as: .zip

Change History (6)

comment:1 Changed 6 years ago by axeld

I guess putting it into BScreen would be a natural choice, as that one is the only class so far that represents the screen without any window relationship.

I would not expose something like GetCursorSerialNumber() to the user, but rather a HasCursorChanged() method -- the house keeping of the update number could easily be hidden within the API.

And finally, having dirty rects would definitely be faster -- to improve user responsiveness, you could still prioritize (or even divide) those rectangles.

comment:2 in reply to:  1 Changed 6 years ago by jackburton

Replying to axeld:

And finally, having dirty rects would definitely be faster -- to improve user responsiveness, you could still prioritize (or even divide) those rectangles.

Indeed. There should be an api (in BScreen, I guess), where an application can subscribe to these drawing events, and the app_server would send a BMessage with a list of BRects which have been touched by drawing operations. I think this has been proposed eons ago (also by me and Marc Flerackers, IIRC :-) ) but we never managed to implement this. The "hard" part would be avoid slowing down drawing in app_server while sending the messages. Having a dedicated thread which sends the messages would be the best option, probably.

comment:3 Changed 6 years ago by jackburton

I found the draft.

Changed 6 years ago by jackburton

Attachment: ScreenchangesAPI.rtf added

Screen changes api proposal draft (rtf)

comment:4 Changed 6 years ago by AGMS

A simpler and very fast way of passing around the dirty rectangles would be to have a global fixed size array of rectangles (used as a circular buffer) and a global counter identifying the next rectangle to be written by the app_server. Client programs have their own copy of the counter to keep track of where they are in the rectangle list. So that clients can detect missing too many updates (missed more than the array size), the app_server just keeps on incrementing the counter up to infinity. Everyone would use the count modulo the array size for indexing the array (so the array should be a power of two in size).

No need for a separate update thread or the worry about lost BMessages when activity gets too intense. For safety, the array and counter would be in a read only memory area for the clients. An atomic add/fetch would be used to update/read the counter and the app_server would write the new rectangle before updating the counter.

It does mean that the clients would be polling the counter to check for rectangles, rather than getting a callback or BMessage when there's a new rectangle. But most of these clients would be doing an update of some sort every frame anyway.

comment:5 Changed 2 years ago by axeld

Owner: changed from axeld to nobody
Status: newassigned
Note: See TracTickets for help on using tickets.