WinAppDriver / AZERTY Keyboard : sendkeys() doesn't send correctly the numbers - numbers

I try to use WinAppDriver for my UI test. Sendkeys() sends QWERTY txt, while I use AZERTY layout.
I manage to relace characters this way but it doesn't work for numbers:
public static async Task<WindowsElement> SendKeyAndWait(this WindowsElement element, string azertyText, int secondsToWaitAfter = 0, int secondsToWaitFirst = 1)
{
await element.ClickAndWait(secondsToWaitFirst);
element.SendKeys(azertyText
.Replace("a", "q")
.Replace("m", ";")
.Replace("z", "w")
.Replace(",", "m") //WinAppDriver ne connait que le clavier qwerty donc q => a
.Replace("1", "&") //semble ne pas fonctionner pour les chiffres
.Replace("0", "à")
);
await Task.Delay(secondsToWaitAfter);
return element;
}
Has anyone already solved this issue ?
Thanks for your answers

This issue is raised and still open (4 years!) on the WinAppDriver repo.
Here's the workaround that a user suggested there.
private static void SwitchToUsKeyboard()
{
var switchKeyboardLayoutActions = new Actions(AppSession);
switchKeyboardLayoutActions.SendKeys(Keys.Control + "0" + Keys.Control);
switchKeyboardLayoutActions.Build();
switchKeyboardLayoutActions.Perform();
}
private static void SwitchToFrKeyboard()
{
var switchKeyboardLayoutActions = new Actions(AppSession);
switchKeyboardLayoutActions.SendKeys(Keys.Control + "1" + Keys.Control);
switchKeyboardLayoutActions.Build();
switchKeyboardLayoutActions.Perform();
}
You would have to setup the US language with a US keyboard first (as well as French in this example). Then you need to add shortcuts for these keyboards.

Related

How to specify Japanese encoding for a UILabel?

When I attempt to display a Japanese string in a UILabel on iOS, it gets displayed using Chinese encoding instead of Japanese.
The two encodings are nearly identical, except in a few specific cases. For example, here is how the character 直 (Unicode U+76F4) is rendered in Chinese (top) vs. Japanese (bottom):
(see here for more examples)
The only time Japanese strings render correctly is when the user's system locale is ja-jp (Japan), but I'd like it to render as Japanese for all users.
Is there any way to force the Japanese encoding? Android has TextView.TextLocale, but I don't see anything similar on iOS UILabel
(Same question for Android. I tagged this Swift/Objective-C because, although I'm looking for a Xamarin.iOS solution, the API is almost the same)
You just need to specify language identifier for attributed string, like
let label = UILabel()
let text = NSAttributedString(string: "直", attributes: [
.languageIdentifier: "ja", // << this !!
.font: UIFont.systemFont(ofSize: 64)
])
label.attributedText = text
Tested with Xcode 13.2 / iOS 15.2
I found an extremely hacky solution that seems to work. However, it seems absurd that there's no way to simply set the locale of a label, so if anyone finds something I missed, please post an answer.
The trick relies on the fact that the Hiragino font displays kanji using Japanese encoding rather than Chinese encoding by default. However, the font looks like shit for English text, so I have to search every string in every label for Japanese substrings and manually change the font using NSMutableAttributedString. The font is also completely broken so I had to find another workaround to fix that.
[assembly: ExportRenderer(typeof(Label), typeof(RingotanLabelRenderer))]
namespace MyApp
{
public class MyLabelRenderer : LabelRenderer
{
private readonly UIFont HIRAGINO_FONT = UIFont.FromName("HiraginoSans-W6", 1); // Size gets updated later
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
// BUGFIX: Chinese encoding is shown by default. Switch to Hiragino font, which correctly shows Japanese characters
// Taken from https://stackoverflow.com/a/71045204/238419
if (Control?.Text != null && e.PropertyName == "Text")
{
var kanjiRanges = GetJapaneseRanges(Control.Text).ToList();
if (kanjiRanges.Count > 0)
{
var font = HIRAGINO_FONT.WithSize((nfloat)Element.FontSize);
var attributedString = Control.AttributedText == null
? new NSMutableAttributedString(Control.Text)
: new NSMutableAttributedString(Control.AttributedText);
// Search through string for all instances of Japanese characters and update the font
foreach (var (start, end) in kanjiRanges)
{
int length = end - start + 1;
var range = new NSRange(start, length);
attributedString.AddAttribute(UIStringAttributeKey.Font, font, range);
// Bugfix: Hiragino font is broken (https://stackoverflow.com/a/44397572/238419) so needs to be adjusted upwards
// jesus christ Apple
attributedString.AddAttribute(UIStringAttributeKey.BaselineOffset, (NSNumber)(Element.FontSize/10), range);
}
Control.AttributedText = attributedString;
}
}
}
// Returns all (start,end) ranges in the string which contain only Japanese strings
private IEnumerable<(int,int)> GetJapaneseRanges(string str)
{
for (int i = 0; i < str.Length; i++)
{
if (IsJapanese(str[i]))
{
int start = i;
while (i < str.Length - 1 && KanjiHelper.IsJapanese(str[i]))
{
i++;
}
int end = i;
yield return (start, end);
}
}
}
private static bool IsJapanese(char character)
{
// An approximation. See https://github.com/caguiclajmg/WanaKanaSharp/blob/792f45a27d6e543d1b484d6825a9f22a803027fd/WanaKanaSharp/CharacterConstants.cs#L110-L118
// for a more accurate version
return character >= '\u3000' && character <= '\u9FFF'
|| character >= '\uFF00';
}
}
}

How to get character entered on Keydown Event in WPF C#

i'm using wpf c# in visual studio
i want to prevent user can enter Arabic character , Just Persian Character
like when user entered this value on keyboard → "ي" change it to "ی"
my means something like this :
when user press button to type "A" on keyboard i want to change this character, first check if is "A" change to "B"
i did it in Windows Form Application , but that code does not work in WPF
My Code in Windows From :
if (e.KeyChar.ToString() == "ي")
{
e.KeyChar = Convert.ToChar("ی");
}
My Code in WPF :
if (e.Key.ToString() == "ي")
{
e.Key.ToString("ی");
}
These codes not working in WPF
Please Help
It's a bit different in WPF.
This works using a english keyboard. Don't know if it will work with Arabic, as the rules might be a little different for inserting characters.
You can try handling the PreviewTextInput event of the TextBox.
XAML:
<TextBox PreviewTextInput="TextBox_OnTextInput" ...
Code:
private void TextBox_OnTextInput(object sender, TextCompositionEventArgs e)
{
var box = (sender as TextBox);
var text = box.Text;
var caret = box.CaretIndex;
if (e.TextComposition.Text == "ي")
{
var newValue = "ی";
//Update the TextBox' text..
box.Text = text.Insert(caret, newValue);
//..move the caret accordingly..
box.CaretIndex = caret + newValue.Length;
//..and make sure the keystroke isn't handled again by the TextBox itself:
e.Handled = true;
}
}

How to trap a PASTE in a TEXT widget

I have a TEXT entry field. I want to limit the entry to letters or digits. Other characters should be converted to an under-score. The following code does this. However when the user pastes into the field, it bypasses the listener and the raw text is put into the field
private class TextKeyVerifyListener implements VerifyListener
{
#Override
public void verifyText( VerifyEvent event )
{
if (Character.isLetterOrDigit( event.character ))
event.text = "" + Character.toUpperCase( event.character );
else if (!Character.isISOControl( event.keyCode ))
event.text = "_";
}
}
How do I trap the paste action so at least I can re-parse the text field. It seems kind of heavy duty to do this in the modify listener for each keystroke. Any solution should be cross-platform :-)
Trapping for CTRL-V might do this, but the user can also use the pop menu and choose paste.
VerifyEvent has a text field containing all the text to be verified. You should be using this rather than the character field. text is set to the full pasted text.
Ok, for anyone else trying to do this:
if (event.keyCode == 0 || !Character.isISOControl( event.keyCode ))
{
StringBuilder text = new StringBuilder();
char[] chars = event.text.toCharArray();
for (char character : chars)
if (Character.isLetterOrDigit( character ))
text.append( Character.toUpperCase( character ) );
else
text.append( "_" ); //$NON-NLS-1$
event.text = text.toString();
}
It's a little heavy for single keystrokes, but it will convert as I wanted.
Thanks!

Extension event loop in Gnome 3.10 vs 3.14

I wrote this accessibility extension:
https://extensions.gnome.org/extension/975/keyboard-modifiers-status/
https://github.com/sneetsher/Keyboard-Modifiers-Status
Which works as supposed in Gnome Shell v3.14 & v3.16 but not in v3.10. It shows the only the initial keyboard modifiers state after i
restarted it and never update it after that.
Here the full code:
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Gdk = imports.gi.Gdk
let button, label, keymap;
function _update() {
let symbols = "⇧⇬⋀⌥①◆⌘⎇";
let state = keymap.get_modifier_state();
label.text = " ";
for (var i=0; i<=8; i++ ) {
if (state & 1<<i) {
label.text += symbols[i];
} else {
//label.text += "";
}
}
label.text += " ";
}
function init() {
button = new St.Bin({ style_class: 'panel-button',
reactive: false,
can_focus: false,
x_fill: true,
y_fill: false,
track_hover: false });
label = new St.Label({ style_class: "state-label", text: "" });
button.set_child(label);
keymap = Gdk.Keymap.get_default();
keymap.connect('state_changed', _update );
Mainloop.timeout_add(1000, _update );
}
function enable() {
Main.panel._rightBox.insert_child_at_index(button, 0);
}
function disable() {
Main.panel._rightBox.remove_child(button);
}
Trying to debug, I modified the code to show (state label + a counter)
let c,button, label, keymap;
c=0;
function _update() {
Gtk.main_iteration_do(false);
c++;
let symbols = "⇧⇬⋀⌥①◆⌘⎇";
//let keymap = Gdk.Keymap.get_default()
let state = keymap.get_modifier_state();
label.text = " ";
for (var i=0; i<=8; i++ ) {
if (state & 1<<i) {
label.text += symbols[i];
} else {
//label.text += "";
}
}
label.text += " "+c+" ";
return true;
}
I can confirm these:
keymap.connect('state_changed', _update ); this signal is never raised
timeout callback works well
label is updated and show the initial state & the incrementing counter
So I think there is something with event loop as it does not pull
state update or does not process its events.
Could you please point me to way to fix this and what's the difference
between v3.10 & v3.14?
Assuming that commenting out the definition of keymap was intentional, check that it is still assigned elsewhere in your code. Have you tried using a -(minus) rather than a _(underscore)? Most events use the former in JS space, rather than the latter and this has been the problem for me when in several cases where I was attaching events to changing the active workspace, where the back-end for Meta.Display fires workspace_switched, the GJS space connects through workspace-switched and there are a lot more examples there.
For official documentation, including the correct event, property and function names for within GJS space, refer to GNOME DevDocs I don't know when it became official, but they state that it is here

ProgressMessageBox Is Not Updating

In GXT (from Sencha) I am attempting to use a ProgressMessageBox to show the user that work is being done, but I am not seeing the message box until after all of the work is complete. Here is the code:
final ProgressMessageBox messageBox = new ProgressMessageBox("Task Description",
"Executing Task...");
messageBox.setProgressText("Calculating...");
messageBox.setPredefinedButtons();
messageBox.show();
for (int i = 0; i < 5; ++i) {
for (long l = 0l; l < 10000000000l; ++l) {
if (l == 12345l) {
MyUtil.info(60, "" + System.currentTimeMillis() / 1000);
}
}
messageBox.updateProgress((double)(i + 1) / 5, "{0}% Complete");
}
This code is in the SelectionHandler of a menu item. Obviously I am not actually just looping a few billion times in the "real" code, but when I perform the work that I want to execute I get the same result ... the message box is shown after all the work has been completed. I see the "info" messages (MyUtil#info is simply a wrapper around the GXT Info capability, which causes an info message to be displayed for the specified number of seconds) ... and on my machine, running the code shown, each message has a value that is about seven seconds greater than the previous message (but they all show up at the same time as the message box).
Is there something that I need to do after calling ProgressMessageBox#updateProgress to force the screen or message box to refresh?
I was able to get this to work by putting the task into a Scheduler#execute method. The example in the Sencha Explorer Demo uses a Timer, but since I don't know how long the execution will take I chose to use the Scheduler approach. Here is the relevant final code:
...
menuItem.addSelectionHandler(new SelectionHandler<Item>() {
#Override
public void onSelection(final SelectionEvent<Item> selectionEvent) {
final ProgressMessageBox messageBox = new ProgressMessageBox("Size All Columns", //
"Resizing Columns...");
messageBox.setProgressText("Calculating...");
// messageBox.setPredefinedButtons();
messageBox.show();
resizeNextColumn(messageBox,
_selectionModel instanceof CheckBoxSelectionModel ? 1 : 0,
_grid.getColumnModel().getColumnCount() - 1);
}
});
...
private void resizeNextColumn(final ProgressMessageBox messageBox,
final int columnIndex,
final int lastColumnIndex) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
resizeColumnToFit(columnIndex);
if (columnIndex == lastColumnIndex) {
messageBox.hide();
_grid.getView().refresh(true);
return;
}
messageBox.updateProgress((double)columnIndex / (lastColumnIndex + 1),
"{0}% Complete");
resizeNextColumn(messageBox, columnIndex + 1, lastColumnIndex);
}
});
}
One thing that didn't appear to work is the messageBox.setPredefinedButtons() call ... when I use this the progress bar in the message box doesn't update at all. I really didn't want an "OK" button on the dialog, but for now it'll have to do. I'm using 3.1.0 of GXT.