From 6085f29d9e88fc6da121c367d5e6603960795ab8 Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Fri, 19 Apr 2024 12:33:55 +0200 Subject: [PATCH] Multi zoom level support for caret This commit scales the caret on a DPI change event on styled text. It uses the line height of the styled text to set on caret. The height and width field in the caret are storing data in points now and not in pixels. We do so to avail the scaling refernece. Also we use SWT.DEFAULT to ignore setting of width. It is useful when we set the new height on DPI change since the preferred width of the caret is loadeed from preferences on the Caret creation. Contributes to #62 and #127 --- .../CommonWidgetsDPIChangeHandlers.java | 25 +++++- .../win32/org/eclipse/swt/widgets/Caret.java | 81 ++++++++++--------- .../org/eclipse/swt/widgets/Display.java | 1 + 3 files changed, 67 insertions(+), 40 deletions(-) rename bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/{internal => custom}/CommonWidgetsDPIChangeHandlers.java (61%) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/CommonWidgetsDPIChangeHandlers.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/custom/CommonWidgetsDPIChangeHandlers.java similarity index 61% rename from bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/CommonWidgetsDPIChangeHandlers.java rename to bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/custom/CommonWidgetsDPIChangeHandlers.java index 1ac53b67756..7c0ab87721a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/CommonWidgetsDPIChangeHandlers.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/custom/CommonWidgetsDPIChangeHandlers.java @@ -11,9 +11,11 @@ * Contributors: * Yatta Solutions - initial API and implementation *******************************************************************************/ -package org.eclipse.swt.internal; +package org.eclipse.swt.custom; +import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.*; import org.eclipse.swt.widgets.*; /** @@ -31,6 +33,7 @@ public class CommonWidgetsDPIChangeHandlers { public static void registerCommonHandlers() { DPIZoomChangeRegistry.registerHandler(CommonWidgetsDPIChangeHandlers::handleItemDPIChange, Item.class); + DPIZoomChangeRegistry.registerHandler(CommonWidgetsDPIChangeHandlers::handleStyledTextDPIChange, StyledText.class); } private static void handleItemDPIChange(Widget widget, int newZoom, float scalingFactor) { @@ -43,4 +46,24 @@ private static void handleItemDPIChange(Widget widget, int newZoom, float scalin item.setImage(image); } } + + private static void handleStyledTextDPIChange(Widget widget, int newZoom, float scalingFactor) { + if (!(widget instanceof StyledText)) { + return; + } + StyledText styledText = (StyledText) widget; + + DPIZoomChangeRegistry.applyChange(styledText.getCaret(), newZoom, scalingFactor); + styledText.getCaret().setSize(SWT.DEFAULT, styledText.getLineHeight()); + + DPIZoomChangeRegistry.applyChange(styledText.defaultCaret, newZoom, scalingFactor); + styledText.defaultCaret.setSize(SWT.DEFAULT, styledText.getLineHeight()); + for (Caret caret : styledText.carets) { + DPIZoomChangeRegistry.applyChange( caret, newZoom, scalingFactor); + caret.setSize(SWT.DEFAULT, styledText.getLineHeight()); + } + + styledText.updateCaretVisibility(); + styledText.setCaretLocations(); + } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java index a8bc59db29a..355d2bcbc33 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java @@ -42,7 +42,7 @@ public class Caret extends Widget { private static Caret currentCaret; Canvas parent; - int x, y, width, height; + int xInPixels, yInPixels, width, height; boolean moved, resized; boolean isVisible; Image image; @@ -127,15 +127,15 @@ public Rectangle getBounds () { Rectangle getBoundsInPixels () { if (image != null) { Rectangle rect = image.getBoundsInPixels (); - return new Rectangle (x, y, rect.width, rect.height); + return new Rectangle (xInPixels, yInPixels, rect.width, rect.height); } if (width == 0) { int [] buffer = new int [1]; if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) { - return new Rectangle (x, y, buffer [0], height); + return new Rectangle (xInPixels, yInPixels, buffer [0], getHeightInPixels()); } } - return new Rectangle (x, y, width, height); + return new Rectangle (xInPixels, yInPixels, getWidthInPixels(), getWidthInPixels()); } /** @@ -189,7 +189,7 @@ public Point getLocation () { } Point getLocationInPixels () { - return new Point (x, y); + return new Point (xInPixels, yInPixels); } /** @@ -230,10 +230,18 @@ Point getSizeInPixels () { if (width == 0) { int [] buffer = new int [1]; if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) { - return new Point (buffer [0], height); + return new Point (buffer [0], getHeightInPixels()); } } - return new Point (width, height); + return new Point (getWidthInPixels(), getHeightInPixels()); +} + +private int getWidthInPixels() { + return DPIUtil.autoScaleUp(width, getZoom()); +} + +private int getHeightInPixels() { + return DPIUtil.autoScaleUp(height, getZoom()); } /** @@ -293,7 +301,7 @@ void killFocus () { void move () { moved = false; setCurrentCaret(this); - if (!OS.SetCaretPos (x, y)) return; + if (!OS.SetCaretPos (xInPixels, yInPixels)) return; resizeIME (); } @@ -354,15 +362,15 @@ void resize () { long hwnd = parent.handle; OS.DestroyCaret (); long hBitmap = image != null ? Image.win32_getHandle(image, getZoom()) : 0; - int width = this.width; - if (image == null && width == 0) { + int widthInPixels = this.getWidthInPixels(); + if (image == null && widthInPixels == 0) { int [] buffer = new int [1]; if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) { - width = buffer [0]; + widthInPixels = buffer [0]; } } - OS.CreateCaret (hwnd, hBitmap, width, height); - OS.SetCaretPos (x, y); + OS.CreateCaret (hwnd, hBitmap, widthInPixels, getHeightInPixels()); + OS.SetCaretPos (xInPixels, yInPixels); OS.ShowCaret (hwnd); move (); } @@ -396,15 +404,7 @@ void restoreIMEFont () { public void setBounds (int x, int y, int width, int height) { checkWidget(); int zoom = getZoom(); - setBoundsInPixels(DPIUtil.autoScaleUp(x, zoom), DPIUtil.autoScaleUp(y, zoom), DPIUtil.autoScaleUp(width, zoom), DPIUtil.autoScaleUp(height, zoom)); -} - -void setBoundsInPixels (int x, int y, int width, int height) { - boolean samePosition = this.x == x && this.y == y; boolean sameExtent = this.width == width && this.height == height; - if (samePosition && sameExtent && isCurrentCaret()) return; - this.x = x; - this.y = y; this.width = width; this.height = height; if (sameExtent) { @@ -414,6 +414,14 @@ void setBoundsInPixels (int x, int y, int width, int height) { resized = true; if (isVisible && hasFocus ()) resize (); } + setBoundsInPixels(DPIUtil.autoScaleUp(x, zoom), DPIUtil.autoScaleUp(y, zoom), sameExtent); +} + +private void setBoundsInPixels (int xInPixels, int yInPixels, boolean sameExtent) { + boolean samePosition = this.xInPixels == xInPixels && this.yInPixels == yInPixels; + if (samePosition && sameExtent && isCurrentCaret()) return; + this.xInPixels = xInPixels; + this.yInPixels = yInPixels; } /** @@ -431,25 +439,21 @@ void setBoundsInPixels (int x, int y, int width, int height) { */ public void setBounds (Rectangle rect) { if (rect == null) error (SWT.ERROR_NULL_ARGUMENT); - setBoundsInPixels(DPIUtil.autoScaleUp(rect, getZoom())); -} - -void setBoundsInPixels (Rectangle rect) { - setBoundsInPixels (rect.x, rect.y, rect.width, rect.height); + setBounds(rect.x, rect.y, rect.width, rect.height); } void setFocus () { long hwnd = parent.handle; long hBitmap = 0; if (image != null) hBitmap = Image.win32_getHandle(image, getZoom()); - int width = this.width; - if (image == null && width == 0) { + int widthInPixels = this.getWidthInPixels(); + if (image == null && widthInPixels == 0) { int [] buffer = new int [1]; if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) { - width = buffer [0]; + widthInPixels = buffer [0]; } } - OS.CreateCaret (hwnd, hBitmap, width, height); + OS.CreateCaret (hwnd, hBitmap, widthInPixels, getHeightInPixels()); move (); setIMEFont (); if (isVisible) OS.ShowCaret (hwnd); @@ -543,9 +547,9 @@ public void setLocation (int x, int y) { setLocationInPixels(DPIUtil.autoScaleUp(x, zoom), DPIUtil.autoScaleUp(y, zoom)); } -void setLocationInPixels (int x, int y) { - if (this.x == x && this.y == y && isCurrentCaret()) return; - this.x = x; this.y = y; +private void setLocationInPixels (int xInPixels, int yInPixels) { + if (this.xInPixels == xInPixels && this.yInPixels == yInPixels && isCurrentCaret()) return; + this.xInPixels = xInPixels; this.yInPixels = yInPixels; moved = true; if (isVisible && hasFocus ()) move (); } @@ -590,12 +594,11 @@ public void setLocation (Point location) { */ public void setSize (int width, int height) { checkWidget(); - setSizeInPixels(DPIUtil.autoScaleUp(width, getZoom()), DPIUtil.autoScaleUp(height, getZoom())); -} - -void setSizeInPixels (int width, int height) { if (this.width == width && this.height == height && isCurrentCaret()) return; - this.width = width; this.height = height; + if(width != SWT.DEFAULT) { + this.width = width; + } + this.height = height; resized = true; if (isVisible && hasFocus ()) resize (); } @@ -617,7 +620,7 @@ public void setSize (Point size) { checkWidget(); if (size == null) error (SWT.ERROR_NULL_ARGUMENT); size = DPIUtil.autoScaleUp(size, getZoom()); - setSizeInPixels(size.x, size.y); + setSize(size.x, size.y); } /** diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index a399914081e..35daca978f7 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -21,6 +21,7 @@ import java.util.function.*; import org.eclipse.swt.*; +import org.eclipse.swt.custom.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.ole.win32.*;