I am using the SDL-2.0.3 along with NDK-r10e, I'm attempting to make the return button switch the app to the background so I tried to use the function SDL_MinimizeWindow() but It does nothing ! is this a bug or do I miss something ?
here is my code :
if(event.key.keysym.sym == SDLK_AC_BACK)
{
SDL_MinimizeWindow(window);
SDL_Log("window minimized !\n");
}
everything just work fine and I get the log message when the button is pressed but the window is not minimized
That doesn't appear to be supported on Android (there's not really anything corresponding to minimizing a "window" on Android, unless you count finishing an Activity).
The SDL_MinimizeWindow function looks like this:
void
SDL_MinimizeWindow(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, );
if (window->flags & SDL_WINDOW_MINIMIZED) {
return;
}
SDL_UpdateFullscreenMode(window, SDL_FALSE);
if (_this->MinimizeWindow) {
_this->MinimizeWindow(_this, window);
}
}
Where _this is an SDL_VideoDevice *, which is set to point to an SDL_VideoDevice for the appropriate platform at runtime. The Android video driver only sets up the following 3 Window-related functions:
device->CreateWindow = Android_CreateWindow;
device->SetWindowTitle = Android_SetWindowTitle;
device->DestroyWindow = Android_DestroyWindow;
Trying to perform any other operations on an SDL_Window on Android is likely to do nothing.
Some further information in the form of a couple of lines of code from SDL_androidwindow.c:
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */
window->flags |= SDL_WINDOW_FULLSCREEN; /* window is always fullscreen */
Related
I'm building a little browser app using android webview and I've been using window.getSelection() in javascript to get the nature of any text selected by the user and show a custom context menu based on the type of the selection i.e. whether it's a range, a carat, whether it's in a contenteditable etc.
This works fine unless the selection is in an iframe, then the browser security measures kick in and prevent me sniffing what has been selected using window.getSelection(). How can I workaround this?
Ideally I need a way to get better information about what was selected from the webview or if that's not possible I need a way to sniff whether the selection occurred in an iframe so I can disable my custom context menu logic and fallback to the default android context menu.
UPDATE/FURTHER CLARIFICATION 07/05/2019:
Seems I wasn't clear enough in my initial description...
My goal is to have a visually and functionally custom menu when selecting content in the webview that can cut/copy/paste as the standard context menu does in any part of the page/iframes etc. e.g.
I realised my original approach using javascript to detect the type of selection and to perform the cut/copy/paste was wrong because it will be blocked by cross origin security in iframes.
What I need is a native android/webview based approach. I've discovered that I can sniff the type of selection in the webview by looking at the items in mode.getMenu() on onActionModeStarted. This will allow me to show the correct buttons in my custom menu UI but I have been unable to manually trigger the same logic that gets called when cut/copy/paste is clicked. I thought I found the solution with webView.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CUT, null); but this doesn't work for some reason so I guess my question really is how can I manually trigger cut/copy/paste on the selected text from webview without using javascript? or any other approach that will allow me to have a custom selection menu with lots of options based on what was selected without hitting the browser security limitations?
Okay I figured out how roughly how to do this.
Step 1) In your activity, override onActionModeStarted and check the menu items available in the default context menu. This gives you a clue as to what the type of selection is and which buttons you will need to show in your custom menu. Also it gives you a reference to the item ID which you can use to later to trigger the action e.g.
systemSelectionMenu = mode.getMenu(); // keep a reference to the menu
MenuItem copyItem = systemSelectionMenu.getItem(0); // fetch any menu items you want
copyActionId = copyItem.getItemId(); // store reference to each item you want to manually trigger
Step 2) Instead of clearing the menu, use setVisible() to hide each menu item you want a custom button for e.g.
copyItem.setVisible(false);
Step 3) In your custom button onclick event you can trigger the copy action using:
myActivity.systemSelectionMenu.performIdentifierAction(myActivity.copyActionId, 0)
You can retrieve iframe's selection only if it has the same origin. Otherwise, you have no chances to track any iframe's events(clicks, touches, key presses, etc.).
const getSelectedText = (win, doc) => {
const isWindowSelectionAvailable = win && typeof win.getSelection != "undefined";
if (isWindowSelectionAvailable) {
return win.getSelection().toString();
}
const hasDocumentSelection = doc && typeof doc.selection != "undefined" && doc.selection.type == "Text";
if (hasDocumentSelection) {
return doc.selection.createRange().text;
}
return '';
}
const doIfTextSelected = (win, doc, cb) => () => {
const selectedText = getSelectedText(win, doc);
if (selectedText) {
cb(selectedText);
}
}
const setupSelectionListener = (win, doc, cb) => {
doc.onmouseup = doIfTextSelected(win, doc, cb);
doc.onkeyup = doIfTextSelected(win, doc, cb);
}
const getIframeWinAndDoc = (iframe) => {
try {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const win = iframe.contentWindow || iframe.contentDocument.defaultView;
return { win, doc };
} catch (e) {
console.error(`${e}`);
return {};
}
}
const callback = console.log;
setupSelectionListener(window, document, callback);
document.querySelectorAll('iframe').forEach(iframe => {
const { win, doc } = getIframeWinAndDoc(iframe, console.log);
// Only for same origin iframes due to https://en.wikipedia.org/wiki/Same-origin_policy
if (win && doc) {
setupSelectionListener(win, doc, callback);
}
})
<h3>Select me</h3>
<div class="container">
<iframe src="https://teimurjan.github.io"></iframe>
</div>
This issue varying from browser to other if it works with internet explorer so it may fall with chrome
Try this
App.util.getSelectedText = function(frameId) {
var frame = Ext.getDom(frameId);
var frameWindow = frame.contentWindow;
var frameDocument = frameWindow.document;
if (frameDocument.getSelection) {
return frameDocument.getSelection();
}
else if (frameDocument.selection) {
return frameDocument.selection.createRange().text;
}
};
Hope it runs fine
Main problem is the window.getSelection() will return selection only for the main context/window. As iframe is the other window and other context, you should call getSelection() from iframe which is "current".
I am writing a Xamarin Forms app (.net standard 2.0). Currently it is only being developed for Android but it may be released for other OSs in future. The scenario I am trying to manage is this:
The user goes into a ContentPage with a single Entry
I give the Entry focus by using native Android code in a custom renderer:
if (e.NewElement != null && e.NewElement is CustomEntry)
{
CustomEntry customEntry = (CustomEntry)e.NewElement;
if(customEntry.GiveFocus)
{
//this messes up the onback behaviour - you have to press onback twice to exit the screen, once to get out of the hidden SIP
Control.RequestFocus();
}
}
I do not want the soft keyboard to pop up automatically. Therefore I have added the below line to the OnCreate of the MainActivity:
Window.SetSoftInputMode(SoftInput.StateAlwaysHidden);
The reason I am requesting focus in the custom renderer and not in the Xamarin Forms Entry is I could see the keyboard popup and then immediately disappear when I requested it in the Xamarin Forms control. I don't want the keyboard to appear as this app will be primarily used by users of industrial devices with a hardware keyboard, but the entry will need to have focus as the users will want to enter text into it straight away.
My problem is the user has to press the back button twice to exit the ContentPage in this scenario. Once to get out of the hidden keyboard (and the Entry loses focus) and then again to exit the page. I want to avoid this - they should be able to exit the page with only one click when the keyboard is hidden. Does anyone know how to resolve this? I have tried overriding OnKeyPreIme in the custom renderer as other answers have suggested but it doesn't appear to detect the back click.
You can use Hide Keyboard method when your entry get focused. It might solved your problem.
public interface IKeyboardHelper
{
void HideKeyboard();
}
For Android use :
public class DroidKeyboardHelper : IKeyboardHelper
{
public void HideKeyboard()
{
var context = Forms.Context;
var inputMethodManager = context.GetSystemService(Context.InputMethodService) as InputMethodManager;
if (inputMethodManager != null && context is Activity)
{
var activity = context as Activity;
var token = activity.CurrentFocus?.WindowToken;
inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
activity.Window.DecorView.ClearFocus();
}
}
}
For iOS :
public class iOSKeyboardHelper : IKeyboardHelper
{
public void HideKeyboard()
{
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
}
}
Use Dependency Injection and call this method while your entry get focused.
Try to use below method for handling back button pressed event.
protected override bool OnBackButtonPressed()
{
// you can handle back button pressed event in Xamarin forms page
return base.OnBackButtonPressed();
}
I've (finally) worked it out. The key is not to override OnKeyPreIME but DispatchKeyEventPreIme instead. This allows you to intercept the 'Back' press. So, in my CustomRenderer I added this method:
public override bool DispatchKeyEventPreIme(KeyEvent e)
{
//if this is back press and the sip is not visible then we need to call the 'OnBack' method at the view model level
if(!SIPVisibleListener.IsSIPVisible && e.KeyCode == Keycode.Back)
{
if(XamarinFormsControl != null && XamarinFormsControl is IOnBackHandler)
{
((IOnBackHandler)XamarinFormsControl).GoBack();
}
}
return base.DispatchKeyEventPreIme(e);
}
IOnBackHandler is an interface I created to handle the back key press. SIPVisibleListener is based on an answer to this question: How do I Detect if Software Keyboard is Visible on Android Device?
Hopefully this will help someone.
I am building this app, that will recognize painting and will display the info about it with the help of AR.
And I need to call multiple image target but not simultaneously, it will only call the image target if it is detected by AR camera.
*Ive tried creating many scenes with Image target on it but I cant call different imagetarget it keeps on reverting to only 1 imagetarget.
This is wat you can see in menu,
Main menu
Start AR camera(This part should have many image target but not detecting it simultaneously)
Help(how to use the app)
Exit
*Im using vuforia in creating AR
Thanks in advance for those who will help me.
This is the imagetarget and its Database
View post on imgur.com
Run the multi target scene sample. There are three target (stone, wood and road).
Each contains the TrackableBehaviour component.
Grab it and disable it in Start. If you do it in Awake it will be set back to active most likely in the Awake of the component itself or via some other manager.
public class TrackerController:MonoBehaviour
{
private IDictionary<string,TrackableBehaviours> trackers = null;
private void Start()
{
this.trackers = new Dictionary<string,TrackableBehaviour>();
var trackers = FindObjectsOfType<TrackableBehaviour>();
foreach(TrackingBehaviour tb in trackers)
{
this.trackers.Add(tb.TrackableName, tb);
tb.enabled = false;
}
}
public bool SetTracker(string name, bool value)
{
if(string.IsNullOrEmpty(name) == true){ return false; }
if(this.trackers.ContainsKey(name) == false){ return false; }
this.trackers[name].enabled = value;
return true;
}
}
The method finds all TrackableBehaviour and places them in a dictionary for easy access. The setting method return boolean, you can change it to throw exception or else.
I've created a minimal working example of an Input box I'd like to develop using a QGraphicsItem. Here is the code (I'd figure the .h is not necessary):
TestEditor::TestEditor()
{
text = "";
boundingBox = QRectF(0,0,200,100);
}
QRectF TestEditor::boundingRect() const{
return boundingBox;
}
void TestEditor::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
painter->setBrush(QBrush(Qt::gray));
painter->drawRect(boundingBox);
painter->setBrush(QBrush(Qt::black));
painter->drawText(boundingBox,text);
}
void TestEditor::keyReleaseEvent(QKeyEvent *event){
qDebug() << "Aca toy";
text = text + event->text();
update();
}
My tester application is simply adding it to a graphics view to test it:
TestEditor *editor = new TestEditor();
editor->setText("Algo de texto como para empezar");
editor->setFlag(QGraphicsItem::ItemAcceptsInputMethod,true);
editor->setFlag(QGraphicsItem::ItemIsFocusable,true);
editor->setFlag(QGraphicsItem::ItemIsSelectable,true);
ui->gvScreen->scene()->addItem(editor);
When I test this on my PC it works fine. When I compile it for android, I get the problem that keyboard doesn't appear so I can't try it out. How can I force the keyboard to appear?
Well In case anyone is wondering I've found a way to force the android keyboard to show.
QInputMethod *keyboard = QGuiApplication::inputMethod();
keyboard->show();
I've lost the code where I used it so I don't rembember if QGuiApplication can be called from anywhere. But if it can't you can simply sotre the pointer to the keyboard from your main form/class and pass it as a parameter to any sort of required item or class
I'm building a mobile AIR app (Android & IOS) with Adobe Flash Builder 4.6 and I'm having this annoying problem.
Because I want to 'catch' the back-key on Android devices I added the following code to my main class:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
private function keyDown(k:KeyboardEvent):void {
if(k.keyCode == Keyboard.BACK) {
backClicked(); // function handling the back-action, not important
k.preventDefault();
}
Now somewhere else - nested in some classes - I've got a textfield:
TF = new TextField();
TF.type = TextFieldType.INPUT;
But when I set focus on the textfield the soft keyboard does appear, but I can't type a single character. When I disable the keylistener: no problem.
Seems like the listener is overriding my input field. Is there any workaround on this?
I have also implemented the back button functionality for my mobile apps , but i used to register keydown event only when my particular view is activated and removed the registered when view get deactivated.
in <s:view ....... viewActivate ="enableHardwareKeyListeners(event)" viewDeactivate="destroyHardwareKeyListeners(event)">
// add listener only for android device
if (Check for android device) {
NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown, false, 0);
NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp, false, 0);
this.setFocus();
}
private function destroyHardwareKeyListeners(event:ViewNavigatorEvent):void
{
if (NativeApplication.nativeApplication.hasEventListener(KeyboardEvent.KEY_DOWN))
NativeApplication.nativeApplication.removeEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown);
if (NativeApplication.nativeApplication.hasEventListener(KeyboardEvent.KEY_UP))
NativeApplication.nativeApplication.removeEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp);
}
private function handleHardwareKeysDown(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.BACK) {
e.preventDefault();
// your code
} else {
}
}
private function handleHardwareKeysUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.BACK)
e.preventDefault();
}
May this can help you.