From 333b97dc3a37c1a722c84743d0f9090ea458cfed Mon Sep 17 00:00:00 2001 From: John Wiggins Date: Fri, 19 Feb 2021 12:21:53 +0100 Subject: [PATCH] Add HiDPI support for Wx (#595) --- enable/wx/base_window.py | 17 +++++++++++------ enable/wx/cairo.py | 5 ++++- enable/wx/gl.py | 5 ++++- enable/wx/image.py | 4 +++- enable/wx/quartz.py | 4 +--- kiva/cairo.py | 2 ++ 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/enable/wx/base_window.py b/enable/wx/base_window.py index f53106007..0fe74adf6 100644 --- a/enable/wx/base_window.py +++ b/enable/wx/base_window.py @@ -177,6 +177,10 @@ def __init__(self, parent, wid=-1, pos=wx.DefaultPosition, # Create the delegate: self.control = control = self._create_control(parent, wid, pos, size) + # Figure out the pixel scale factor + if self.high_resolution: + self.base_pixel_scale = self.control.GetContentScaleFactor() + # Set up the 'erase background' event handler: control.Bind(wx.EVT_ERASE_BACKGROUND, self._on_erase_background) @@ -263,7 +267,8 @@ def _on_close(self, event): def _flip_y(self, y): """ Convert from a Kiva to a wxPython y coordinate """ - return int(self._size[1] - 1 - y) + # Handle the device pixel ratio adjustment here + return int(self._size[1] / self.base_pixel_scale - 1 - y) def _on_erase_background(self, event): pass @@ -325,7 +330,7 @@ def _create_key_event(self, event_type, event): if focus_owner is not None: if event_type == "character": - key = chr(event.GetUniChar()) + key = chr(event.GetUnicodeKey()) if not key: return None else: @@ -333,7 +338,7 @@ def _create_key_event(self, event_type, event): if key_code in KEY_MAP: key = KEY_MAP.get(key_code) else: - key = chr(event.GetUniChar()).lower() + key = chr(event.GetUnicodeKey()).lower() # Use the last-seen mouse coordinates instead of GetX/GetY due # to wx bug. @@ -439,7 +444,7 @@ def _get_control_size(self): """ result = None if self.control: - result = self.control.GetSize() + result = self.control.GetSize() * self.base_pixel_scale return result def _window_paint(self, event): @@ -451,8 +456,8 @@ def set_pointer(self, pointer): """ Set the current pointer (i.e. cursor) shape """ ptr = POINTER_MAP[pointer] - if type(ptr) is int: - POINTER_MAP[pointer] = ptr = wx.StockCursor(ptr) + if isinstance(ptr, type(wx.CURSOR_ARROW)): + POINTER_MAP[pointer] = ptr = wx.Cursor(ptr) self.control.SetCursor(ptr) def set_tooltip(self, tooltip): diff --git a/enable/wx/cairo.py b/enable/wx/cairo.py index 299e6cbfb..135de251b 100644 --- a/enable/wx/cairo.py +++ b/enable/wx/cairo.py @@ -22,7 +22,10 @@ class Window(BaseWindow): def _create_gc(self, size, pix_format="bgra32"): "Create a Kiva graphics context of a specified size" - gc = GraphicsContext((size[0] + 1, size[1] + 1)) + gc = GraphicsContext( + (size[0] + 1, size[1] + 1), + base_pixel_scale=self.base_pixel_scale, + ) gc.translate_ctm(0.5, 0.5) return gc diff --git a/enable/wx/gl.py b/enable/wx/gl.py index dab2e45a1..4eecf94ec 100644 --- a/enable/wx/gl.py +++ b/enable/wx/gl.py @@ -43,7 +43,10 @@ def _create_control(self, parent, wid, pos=wx.DefaultPosition, def _create_gc(self, size, pix_format=None): """ Create a GraphicsContext instance. """ - gc = GraphicsContext((size[0] + 1, size[1] + 1)) + gc = GraphicsContext( + (size[0] + 1, size[1] + 1), + base_pixel_scale=self.base_pixel_scale, + ) if self._pyglet_gl_context is None: self._pyglet_gl_context = FakePygletContext() gc.gl_init() diff --git a/enable/wx/image.py b/enable/wx/image.py index bb38f97ef..e8a52af50 100644 --- a/enable/wx/image.py +++ b/enable/wx/image.py @@ -28,7 +28,7 @@ def _wx_bitmap_from_buffer(buf, width, height): copy[..., 1::4] = arr[..., 1::4] copy[..., 2::4] = arr[..., 0::4] copy[..., 3::4] = arr[..., 3::4] - return wx.BitmapFromBufferRGBA(width, height, np.ravel(copy)) + return wx.Bitmap.FromBufferRGBA(width, height, np.ravel(copy)) class Window(BaseWindow): @@ -41,6 +41,7 @@ def _create_gc(self, size, pix_format="bgra32"): gc = GraphicsContext( (size[0] + 1, size[1] + 1), pix_format=pix_format, + base_pixel_scale=self.base_pixel_scale, bottom_up=bottom_up, ) gc.translate_ctm(0.5, 0.5) @@ -65,6 +66,7 @@ def _window_paint(self, event): self._gc.width(), self._gc.height(), ) + bmp.SetSize(control.GetSize()) wdc.DrawBitmap(bmp, 0, 0) control._dc = None diff --git a/enable/wx/quartz.py b/enable/wx/quartz.py index 50a02be93..8283a1aa9 100644 --- a/enable/wx/quartz.py +++ b/enable/wx/quartz.py @@ -87,9 +87,7 @@ class Window(BaseWindow): def _create_gc(self, size, pix_format="bgra32"): self.dc = wx.ClientDC(self.control) - gc = _WindowGraphicsContext( - self.dc.GetSizeTuple(), get_macport(self.dc) - ) + gc = _WindowGraphicsContext(self.dc.GetSize(), get_macport(self.dc)) gc.begin() return gc diff --git a/kiva/cairo.py b/kiva/cairo.py index d9600dcd7..e6ba64aad 100644 --- a/kiva/cairo.py +++ b/kiva/cairo.py @@ -97,6 +97,8 @@ def draw_to_wxwindow(self, window, x, y): image = wx.EmptyImage(self.width, self.height) image.SetDataBuffer(arr.data) bmp = wx.BitmapFromImage(image, depth=-1) + # Scale HiDPI images to fit window + bmp.SetSize(window.GetSize()) window_dc.BeginDrawing() window_dc.DrawBitmap(bmp, x, y)