On Space Change - Not After (For Mac Spaces) - objective-c

I'm new to Mac development, so I can't tell if what I need to do is even possible.
I need to create an application that gets a callback for when a desktop space is about to change and when it successfully does. I also need to override the change to cancel it if need be. For example:
Space Change Initiated -> Run My Code -> Change Space |OR| Cancel Space Change
The only thing that I could find was: NSWorkspaceActiveSpaceDidChangeNotification which sends a callback when the space has successfully changed. This will not be good enough.
I'm not begging for code btw, just looking for a direction to be pointed in to achieve what I want (if at all possible). I'm open to all suggestions, even if they are in different programming languages.
Thanks in advance.

Related

Why do some applications not accept some sendkeys at some times

This is an issue I've ran into before, but I've always given up solving the problem and worked out a work around. Not today (hopefully).
I'm trying to make a bot for the classic Doom II. I want my bot to have access to the main menu which is accessed via the escape key. Naturally I tried:
sendkeys.send("{ESC}")
No luck. But then something weird happened. I accidently ran the code when I was already on the menu... and it closed the menu (which is normal if you press escape on the menu). So clearly Doom II listens to Sendkeys.
I've since tried sendinput, postmessage, and simulateinput. None have worked (they all have the same behaviour as described with sendkeys).
It would be great if someone could ride in on a white horse and give me code to get around this issue, but outside of that can any one simply explain this behaviour to me?
It seems that Zandronum does not accept virtual keys to be sent to it when the game is running (not paused). I'm not sure but it seems that virtual keys might actually be window messages, like Andrew Morton said (or they're at least something similar...). The workaround to this was to send a hardware scan code instead of a virtual key code.
A hardware scan code appears to be the code sent by the actual keyboard when pressing a key, while a virtual key code is the key which the system interprets from the scan code (reference).
So I managed to send keystrokes to Zandronum (both fullscreen and windowed) using a few WinAPI functions:
SendInput() which is used to send the actual keyboard input.
MapVirtualKeyEx() which is used to convert key codes to scan codes, or vice versa.
GetKeyboardLayout() which is used to get the user's current keyboard layout (I, for example, have a Swedish keyboard).
By using the below helper class (or more correctly: wrapper) that I built you may now send keystrokes (hardware or not) in a simple manner, with a larger variety of keys than what SendKeys.Send() includes. You may use any key in the System.Windows.Forms.Keys enumeration.
This was tested with Zandronum and works completely:
InputHelper.Keyboard.PressKey(Keys.Escape, True) 'True = Send key as hardware scan code.
EDIT (2019-09-20)
InputHelper has since long been moved to its own library. The answer has been updated to reflect this change.
Download InputHelper from GitHub:
https://github.com/Visual-Vincent/InputHelper/releases
Just for fun, I also managed to find a list of scan codes on the MSDN: https://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx
Since I'm a Doom fan myself and familiar with how it works, perhaps you should (per your old question) also make sure that you have selected New Game in the menu before you make it press enter?
Zandronum is aware of the names of the menu items, so you just have to give it the first letter and it will jump to the item starting with it:
InputHelper.Keyboard.PressKey(Keys.Escape, True) 'Open the menu.
System.Threading.Thread.Sleep(100) 'Small delay to let the menu open.
InputHelper.Keyboard.PressKey(Keys.N, True) 'Jump to the "New Game" menu item.
InputHelper.Keyboard.PressKey(Keys.Enter, True) 'Go into the "New Game" menu.
InputHelper.Keyboard.PressKey(Keys.Enter, True) 'Start a new game.
I've tested the above code in-game, running in fullscreen mode. Works like a charm.

Programmatically open NSWindow in another Desktop (Space)

In my OSX Project I want to:
identify the Desktop (one of the expose Spaces) where a NSWindow resides;
open a NSWindow in a determined Space, not only on current Space.
Is there a way to do these simple tasks?
Exploring the documentation (NSWindowController, NSWindow, NSScreen) I can't find anything regarding multiple Desktop Management.
Thanks in advance!
You'd think there would be some API for working with Spaces, but there really isn't. You can use CGWindowListCopyWindowInfo to determine which Space a particular window is on, but there's no easy way to open a particular window on a specific space.
There is private API to move windows between spaces, of course. Whether you want to use this in your application depends on your needs - you couldn't use it on a Mac App Store application, obviously.
Found a copy-of-a-copy of the reverse-engineered header I was looking for:
https://gist.github.com/rjw57/5495406

Stop execution in smalltalk

I´d like to know how can I stop execution in smalltalk. I entered an infinite loop and don´t want to loose the code that´s written. I tried using pause button but doesn´t seem to be right.
Normally, even if you are unable to stop execution, you should be able to get the code changes you made back from the .changes file. If you can restart the image, there is a 'recover lost changes' menu entry. Always first make a backup copy of the changes and image files before trying this. (In Pharo/Squeak. Other smalltalk have similar possibilities)
it depends on the dialect and possibly keyboard settings.
try CMD-. or CTRL-., which works in most dialects.

How to return NSLocalizedString as write in the code

Is there a way to get a NSLocalizedString in its untranslated states, for example getting it from a NSTexfield/label or popup button as below:
_mylabel.stringValue
or
[_myPopupButton titleOfSelectedItem];
Obviously returns a translated string depending on the current OS language.
This is inconvenient if I want to know and use a statement comparing what I find at the time, whereas users can also translate or adjust to their liking the stringsfile.
Any suggestion or workaround?
Initially the problem was that I used "NSUserDefaults standardUserDefaults" to save what was on the buttons on a plist, so when I restart the app would have taken those descriptions initially were created using simple strings if the plist did not contain all the dictionary needed (to return into my button), as if app was open for the first time).
It's enough to localize everything, even when re-reading or create the "empty" settings, so it does not matter if the preferences are written in another language: my button now return what the app found on the plist created by "NSUserDefaults standardUserDefaults"!
(sorry for my poor English)

UITextInput - Is it OK to return Incorrect 'beginningOfDocument' & 'endOfDocument'?

I'm creating my own Text Editor in iOS using Core Text. Pretty much everything works great with one exception: Stuff really starts to slow down when the text document is "large". I've discovered that iOS is requesting the entire document text on every change, including selection changes (at least, when I notify the UITextInputDelegate of selection changes). Part of the problem is that I've already optimized my Core Text code by splitting up the document into paragraphs and rendering only the paragraphs that change. But doing this also split up the document string (which is a NSAttributedString) into the separate 'paragraph objects'. So when iOS requests the entire text document, I have to combine all those strings into one string, which takes time and memory.
My solution is to give iOS incorrect UITextPosition's for the beginningOfDocument and endOfDocument methods, limiting those positions to the paragraph(s) intersecting the current selection. This is actually working very well. iOS is now only requesting the current paragraph(s) of the change, which has completely eliminated the slow-down.
So far, so good, but I'm a little worried that this might break something. I've tested this a bit and nothing is broken, but Text Editors can be hard to test (who knows if it'll break in some edge condition).
I have 2 question:
Should iOS be requesting the entire document text on each change? If not, then perhaps some other method in my UITextInput protocol methods that are returning the wrong value, somehow causing iOS to request the entire document.
Does anyone know if this will actually break anything?
Alright, I've been testing this for quite a while now and I've finally found a place where using this technique will break functionality. UITextInput uses beginningOfDocument and endOfDocument to determine whether it has room to "move" when you press the arrow keys on a bluetooth keyboard. Returning only the beginning and end of the currently selected paragraph(s) cause it to ignore the 'arrow' buttons when it is at the beginning or end of that paragraph and those arrows indicate an attempt to move outside what it thinks is the beginning/end of the document. It's easy enough to fix. If the currently selection begins at the beginning/end of a paragraph, I now also return the previous/next paragraph as part of the document, respectively.