Bug 514307 - [HiDPI][API]SWT Custom Cursors are not autoscaled on high res displays
Summary: [HiDPI][API]SWT Custom Cursors are not autoscaled on high res displays
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.7   Edit
Hardware: PC All
: P3 enhancement (vote)
Target Milestone: 4.8   Edit
Assignee: Lakshmi P Shanmugam CLA
QA Contact:
URL:
Whiteboard:
Keywords: api
Depends on: 480639
Blocks: 517055
  Show dependency tree
 
Reported: 2017-03-28 06:21 EDT by Peter Seeberger CLA
Modified: 2018-04-24 12:42 EDT (History)
4 users (show)

See Also:


Attachments
Testprogramm for cursor problem in SWT 4.7.0. Oxygen when using two monitors with different zoom level. (3.49 KB, text/plain)
2017-05-02 10:59 EDT, Peter Seeberger CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Seeberger CLA 2017-03-28 06:21:47 EDT
Szenario:
- High Resolution Environment Windows 10 Display size 3840 x 2160.
- Eclipse Oxygen with Plugin development.


When I create a custom Cursor using: 

new Cursor(display, image.getImageData(), x,y);


The Cursor is not autoscaled on high resolution displays. The Image which is used to create the custom Cursor was created in Memory and is autoscaled by swt to fit high resolution displays. Nevertheless, when I create the cursor using the code above, this autoscale gets lost and the cursor looks to small (half the required size).

I guess the reason is, that getImageData does not retrieve the high resolution autoscaled internal image data but rather a downscaled version. 

There should be an additional constructor for custom cursors like:


new Cursor(display, image, x,y);

which utilizes the high resolution image data and Shows a reasonable size on high resolution szenarios.
Comment 1 Peter Seeberger CLA 2017-05-02 10:59:02 EDT
Created attachment 268118 [details]
Testprogramm for cursor problem in SWT 4.7.0. Oxygen when using two monitors with different zoom level.

With the introduction of new laptops with high resolution displays (3840 x 2160), custom cursors that are created from an SWT Image need to use
the getImageDataAtCurrentZoom method rather than getImageData.

Unfortunatly however, when you connect a legacy monitor to such a high def laptop and set the zoom level of the laptop to 200 % and the zoom level of the external monitor to 100%,
which is necessary with respect ot the lower pixel resolution, you end up with cursors that twice as big on the external monitor.

On the other hand if you use getImageData. The cursor looks fine on the external monitor, but to small on the high res laptop.

There should be a new Cursor(image...) constructor which takes the appropriate custom cursor image depending on the monitor where the shell is currently placed.
Or at least there should be a way to find out on which resolution a Monitor is currently working.
Comment 2 Niraj Modi CLA 2017-05-03 05:32:02 EDT
Currently Cursor only accepts ImageData in constructor and in order to pass ImageData at various zoom, we will need below new constructor in Cursor class:
new Cursor(display, ImageDataProvider, x, y);
Comment 3 Lakshmi P Shanmugam CLA 2018-02-21 06:08:46 EST
I investigated this issue further and there are 2 proposals:

1. As Niraj suggested, we can provide a new constructor for Cursor, something like new Cursor(display, ImageDataProvider, x, y). The client needs to provide the ImageData for different zoom using the ImageDataProvider. SWT has to use the correct ImageData for the Cursor based on the DPI and also automatically switch the Cursor when the DPI changes.
We also need to find a way to pass the hotspots for the corresponding ImageData. 
From implementation POV, this could be a bit complex to switch the Cursor when the DPI changes.

2. As suggested in comment#1 and in the TestProgram, we can provide a new API Monitor.getZoom(). This can be used in the mouse listener such as MouseEnter to update the Cursor when the zoom value changes. This API would be more straightforward to implement but client code would have to track the DPI change and handle the creation of the correct Cursors for the corresponding DPI.
Comment 4 Lakshmi P Shanmugam CLA 2018-02-21 07:06:26 EST
While testing I found that the snippet doesn't work on Mac. Setting a custom control on a Control doesn't seem to be working on Mac. Will open a separate bug to track this.
Comment 5 Lakshmi P Shanmugam CLA 2018-03-05 07:33:29 EST
(In reply to Lakshmi Shanmugam from comment #3)
> I investigated this issue further and there are 2 proposals:
> 
> 1. As Niraj suggested, we can provide a new constructor for Cursor,
> something like new Cursor(display, ImageDataProvider, x, y). The client
> needs to provide the ImageData for different zoom using the
> ImageDataProvider. SWT has to use the correct ImageData for the Cursor based
> on the DPI and also automatically switch the Cursor when the DPI changes.
> We also need to find a way to pass the hotspots for the corresponding
> ImageData. 
> From implementation POV, this could be a bit complex to switch the Cursor
> when the DPI changes.
> 

I investigated Option 1 further and found that on Mac, we can add multiple Image representations to the Cursor Image and the Image is dynamically switched by the OS based on the zoom. Tried to emulate this behavior on Windows, but on Windows/GTK, one Cursor handle can have only one associated image. So, the Cursor class will need to maintain 2 handles and use the correct one for the monitor on which it's used. Also, we should update the Cursor if the DPI changes dynamically.
Comment 6 Lakshmi P Shanmugam CLA 2018-03-05 07:38:51 EST
(In reply to Lakshmi Shanmugam from comment #3)
> I investigated this issue further and there are 2 proposals:
> 
> 2. As suggested in comment#1 and in the TestProgram, we can provide a new
> API Monitor.getZoom(). This can be used in the mouse listener such as
> MouseEnter to update the Cursor when the zoom value changes. This API would
> be more straightforward to implement but client code would have to track the
> DPI change and handle the creation of the correct Cursors for the
> corresponding DPI.

The API Monitor.getZoom() will be addressed by Bug 480639.
Comment 7 Lakshmi P Shanmugam CLA 2018-03-05 07:41:17 EST
(In reply to Lakshmi Shanmugam from comment #4)
> While testing I found that the snippet doesn't work on Mac. Setting a custom
> control on a Control doesn't seem to be working on Mac. Will open a separate
> bug to track this.

The snippet doesn't work on Linux/GTK as well. Works only on windows.
Comment 8 Lakshmi P Shanmugam CLA 2018-04-18 01:28:29 EDT
(In reply to Lakshmi Shanmugam from comment #7)
> (In reply to Lakshmi Shanmugam from comment #4)
> > While testing I found that the snippet doesn't work on Mac. Setting a custom
> > control on a Control doesn't seem to be working on Mac. Will open a separate
> > bug to track this.
> 
> The snippet doesn't work on Linux/GTK as well. Works only on windows.

Opened Bug 533722 to track this.
Comment 9 Lakshmi P Shanmugam CLA 2018-04-24 12:42:49 EDT
(In reply to Lakshmi Shanmugam from comment #6)
> (In reply to Lakshmi Shanmugam from comment #3)
> > I investigated this issue further and there are 2 proposals:
> > 
> > 2. As suggested in comment#1 and in the TestProgram, we can provide a new
> > API Monitor.getZoom(). This can be used in the mouse listener such as
> > MouseEnter to update the Cursor when the zoom value changes. This API would
> > be more straightforward to implement but client code would have to track the
> > DPI change and handle the creation of the correct Cursors for the
> > corresponding DPI.
> 
> The API Monitor.getZoom() will be addressed by Bug 480639.

The Monitor.getZoom() API is now available and can be used to address the issue reported in the bug.