I'm writing a script for a game (DotA 2 - Invoker) so that for example when I press 1 it would steal it and instead send the keyboard events wwe sequentially, so the game shouldn't receive the key event 1.
XGrabKeyboard(display, Dota2Win, False, GrabModeSync, GrabModeSync, CurrentTime);
I can't achieve that with something like this, because the game still receives 1 before XSendEvent wwe:
I think xlib is unable to do what I want so the only way I can think of is to poll the device directly (/dev/input/event1 or something), if so, then please show me an example.
(Also, I need C API solutions. so, no python please.)
Related
I'm working on a custom cross platform UI library that needs a synchronous "ShowPopup" method that shows a popup, runs an event loop until it's finished and automatically cancels when clicking outside the popup or pressing escape. Keyboard, mouse and scroll wheel events need to be dispatched to the popup but other events (paint, draw, timers etc...) need to be dispatched to their regular targets while the loop runs.
Edit: for clarification, by popup, I mean this kind of menu style popup window, not an alert/dialog etc...
On Windows I've implemented this fairly simply by calling GetMessage/DispatchMessage and filtering and dispatching messages as appropriate. Works fine.
I've much less experience with Cocoa/OS X however and finding the whole event loop/dispatch paradigm a bit confusing. I've seen the following article which explains how to implement a mouse tracking loop which is very similar to what I need:
http://stpeterandpaul.ca/tiger/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/chapter_5_section_4.html
but... there's some things about this that concern me.
The linked article states: "the application’s main thread is unable to process any other requests during an event-tracking loop and timers might not fire". Might not? Why not, when not, how to make sure they do?
The docs for nextEventMatchingMask:untilDate:inMode:dequeue: states "events that do not match one of the specified event types are left in the queue.". That seems a little odd. Does this mean that if an event loop only asks for mouse events then any pressed keys will be processed once the loop finishes? That'd be weird.
Is it possible to peek at a message in the event queue without removing it. eg: the Windows version of my library uses this to close the popup when it's clicked outside, but leaves the click event in the queue so that clicking outside the popup on a another button doesn't require a second click.
I've read and re-read about run loop modes but still don't really get it. A good explanation of what these are for would be great.
Are there any other good examples of implementing an event loop for a popup. Even better would be pseudo-code for what the built in NSApplication run loop does.
Another way of putting all this... what's the Cocoa equivalent of Windows' PeekMessage(..., PM_REMOVE), PeekMessage(..., PM_NOREMOVE) and DispatchMessage().
Any help greatly appreciated.
What exactly is a "popup" as you're using the term? That term means different things in different GUI APIs. Is it just a modal dialog window?
Update for edits to question:
It seems you just want to implement a custom menu. Apple provides a sample project, CustomMenus, which illustrates that technique. It's a companion to one of the WWDC 2010 session videos, Session 145, "Key Event Handling in Cocoa Applications".
Depending on exactly what you need to achieve, you might want to use an NSAlert. Alternatively, you can use a custom window and just run it modally using the -runModalForWindow: method of NSApplication.
To meet your requirement of ending the modal session when the user clicks outside of the window, you could use a local event monitor. There's even an example of just such functionality in the (modern, current) Cocoa Event Handling Guide: Monitoring Events.
All of that said, here are (hopefully no longer relevant) answers to your specific questions:
The linked article states: "the application’s main thread is unable to process any other requests during an event-tracking loop and
timers might not fire". Might not? Why not, when not, how to make
sure they do?
Because timers are scheduled in a particular run loop mode or set of modes. See the answer to question 4, below. You would typically use the event-tracking mode when running an event-tracking loop, so timers which are not scheduled in that mode will not run.
You could use the default mode for your event-tracking loop, but it really isn't a good idea. It might cause unexpected re-entrancy.
Assuming your pop-up is similar to a modal window, you should probably use NSModalPanelRunLoopMode.
The docs for nextEventMatchingMask:untilDate:inMode:dequeue:
states "events that do not match one of the specified event types are
left in the queue.". That seems a little odd. Does this mean that if
an event loop only asks for mouse events then any pressed keys will be
processed once the loop finishes? That'd be weird.
Yes, that's what it means. It's up to you to prevent that weird outcome. If you were to read a version of the Cocoa Event Handling Guide from this decade, you'd find there's a section on how to deal with this. ;-P
Is it possible to peek at a message in the event queue without removing it. eg: the Windows version of my library uses this to close
the popup when it's clicked outside, but leaves the click event in the
queue so that clicking outside the popup on a another button doesn't
require a second click.
Yes. Did you notice the "dequeue:" parameter of nextEventMatchingMask:untilDate:inMode:dequeue:? If you pass NO for that, then the event is left in the queue.
I've read and re-read about run loop modes but still don't really get it. A good explanation of what these are for would be great.
It's hard to know what to tell you without knowing what you're confused about and how the Apple guide failed you.
Are you familiar with handling multiple asynchronous communication channels using a loop around select(), poll(), epoll(), or kevent()? It's kind of like that, but a bit more automated. Not only do you build a data structure which lists the input sources you want to monitor and what specific events on those input sources you're interested in, but each input source also has a callback associated with it. Running the run loop is like calling one of the above functions to wait for input but also, when input arrives, calling the callback associated with the source to handle that input. You can run a single turn of that loop, run it until a specific time, or even run it indefinitely.
With run loops, the input sources can be organized into sets. The sets are called "modes" and identified by name (i.e. a string). When you run a run loop, you specify which set of input sources it should monitor by specifying which mode it should run in. The other input sources are still known to the run loop, but just ignored temporarily.
The -nextEventMatchingMask:untilDate:inMode:dequeue: method is, more or less, running the thread's run loop internally. In addition to whatever input sources were already present in the run loop, it temporarily adds an input source to monitor events from the windowing system, including mouse and key events.
Are there any other good examples of implementing an event loop for a popup. Even better would be pseudo-code for what the built in
NSApplication run loop does.
There's old Apple sample code, which is actually their implementation of GLUT. It provides a subclass of NSApplication and overrides the -run method. When you strip away some stuff that's only relevant for application start-up or GLUT, it's pretty simple. It's just a loop around -nextEventMatchingMask:... and -sendEvent:.
I am writing a small proof of concept for detecting extra inputs across mouses and keyboards on Windows, is it possible and how do I go about detecting input from a large amount of buttons in the Windows API? From what I have read, there is only support for 5 buttons but many mice have more buttons than that, is my question even possible with the Windows API, is it possible at all within the constraints of Windows?
You can use the Raw Input API to receive WM_INPUT messages directly from the mouse/keyboard driver. There are structure fields for the 5 standard mouse buttons (left, middle, right, x1, and x2). Beyond the standard buttons, additional buttons are handled by vendor-specific data that you would have to code for as needed. The API can give you access to the raw values, but you will have to refer to the vendor driver documentation for how to interpret them. Sometimes extra buttons are actually reported as keyboard input instead of mouse input.
Or, try using the DirectInput API to interact with DirectInput devices to receive Mouse Data and Keyboard Data.
Or, you could use the XInput API, which is the successor of DirectInput. However, XInput is more limited than DirectInput, as it is designed primarily for interacting with the Xbox 360 controller, whereas DirectInput is designed to interact with any controller. See XInput and DirectInput for more details.
Very simple: use GetKeyState
SHORT WINAPI GetKeyState(
_In_ int nVirtKey
);
Logic is next:
Ask user not to press buttons
Loop GetKeyState for all buttons 0-255
Drop pressed buttons state (some virtual keys can be pressed even it not pressed, not know why)
Now start keys monitor thread for rest keys codes and save them to any structure (pause between loop is 25ms is enough)
Ask user to press button
From keys monitor array you will see the any pressed buttons by user
Direct input and all other is more usable for other user input devices. For keyboard and mouse - GetKeyState is best.
I’m working on an application that uses the great MASShortcut repository by Shpakovski. I reference this to ask if there is a way to register a shortcut for Capslock in the same way that Shpakovski does in his repository?
It seems that I can’t register 0xffff (Key Codes shows this as Capslock) as a valid shortcut. Even if I combine it with the modifier keys. I also want to catch the press before it toggles the system’s Capslock functionality.
I’m aware that I could listen to all keystrokes and just catch the Capslock when it occurs but I want to avoid this behaviour since I feel it’s potentially insecure and will also decrease the overall system performance.
Edit: I already took a look at some working C++ / C# libraries for Windows which implement this feature. They seem to override the system’s Capslock flag continuously which I found pretty odd. I’m basically having 2 problems here:
1. How to catch the Capslock press without having a keystroke listener all the time
2. How to do so without triggering the system’s Capslock functionality.
One possibility could be to overwrite sendEvent: in your NSApplication delegate. From Apples documentation:
You rarely invoke sendEvent: directly, although you might want to
override this method to perform some action on every event. sendEvent:
messages are sent from the main event loop (the run method).
sendEvent: is the method that dispatches events to the appropriate
responders—NSApp handles application events, the NSWindow object
indicated in the event record handles window-related events, and mouse
and key events are forwarded to the appropriate NSWindow object for
further dispatching.
You could evaluate if the current event has the modifier key pressed and act upon that.
Edit:
For background processing Quartz event taps can be used. If that leads to a rejection, I don't know.
I have been building a very small game in the Windows API, and in the main message loop I use GetAsyncKeyState() to test if a user is pressing the arrow buttons. I use this instead of WM_KEYDOWN because with WM_KEYDOWN there is an initial pause after the first press, and I don't want to modify a user's settings. My antivirus program flags the game as a keylogger program, is there an alternative way about this?
How is the anti-virus program supposed to guess that you are not using GetAsyncKeyState() to spy on the keyboard and log keys? You tell it of course, make an exclusion. If you're worried that your future customers are not so easily convinced then go back to using WM_KEYDOWN/UP. Use an array of 256 bools to keep track of the key state. Set it to true on DOWN, regardless of how many you get, false on UP. Also check if the scanner is happy when you stop calling the API function when your app loses focus. Pay attention to WM_ACTIVATEAPP.
Hi i want to make a sort of a bot for WLM,
But the normal controlsend in autoit wont work
the basic question is how can i send a text to the windows live messenger window Without activating it?
Example:
There is someone in WLM with the window active called "Joop" I do:
ControlClick("Joop","","[CLASS:DirectUIHWND; INSTANCE:2]","Left",1,322,507)
ControlSend("Joop","","[CLASS:DirectUIHWND; INSTANCE:2]","Hi Joop")
this doesn't work however when I do this
WinActivate("Joop","")
ControlClick("Joop","","[CLASS:DirectUIHWND;INSTANCE:2]","Left",1,322,507)
ControlSend("Joop","","[CLASS:DirectUIHWND; INSTANCE:2]","Hi Joop")
it does work however now its activated what i dont want.
there is a problem with the window the whole msn talk window is one window so no extra control to type in thats why i tried the contolClick on the coordinates of the typing screen without succ6
this is the summary.
Text:
Position: 0, 28
Size: 882, 607
ControlClick Coords: 282, 180
Style: 0x56000000
ExStyle: 0x00010000
Handle: 0x00190916
>>>> Mouse <<<<
Position: 1885, 557
Cursor ID: 0
Color: 0xFFFFFF
>>>> StatusBar <<<<
>>>> Visible Text <<<<
>>>> Hidden Text <<<<
CVoiceVideoAvatarHostWindow
does anyone know how to get something in that textfield without activating it (so it can run on background) and using a lame function like send.
OR how can i send a text to the windows live messenger window Without activating it
Thanks
Matthy
MSN is purposefully resisting automation. It's not a limitation of the Windows API. If your goal is to automate a MSN chat, you can do so either by directly sending the TCP packets, or by automating another application which supports MSN (Digsby, Pidgin, etc.) and which works better with automation.
By directly sending the TCP packets you are writing your own program, from scratch, which to the outside world behaves just as MSN. There are user-made documentation about the protocol. One that I have used in the past is here: http://www.hypothetic.org/docs/msn/notification/authentication.php but I am entirely unsure whether it is still up-to-date. If you are familiar with networking, TCP, packet capturing and replaying, then I do suggest going this route as it's the most stable, long-term approach. (And I think: The most fun.)
However, not all projects demand a stable and long-term approach. It seems to me like you were just messing with automating some of the applications you happened to have on your computer, and MSN is of course one of the more interesting ones. Microsoft decided that when they built the MSN client it should not be made easy for anyone to try and automate the application. I think this was mostly done to prevent spam. In the early days it worked, because other people hadn't yet publically documented the protocol. And thus anyone who wanted to spam now had to make a costly investment.
If you do decide to continue with automating the official MSN client, or any other application that resists automation, there are a few tricks that you can try:
ControlSend without specifying the control parameter (use empty string "")
ControlClick on the window with specifying coordinates with using empty string for control parameter again
Eventually, simply Send/MouseClick with optional BlockInput
There are a lot more combinations that you can try (especially ControlX functions) that sometimes miraculously will work, but remember that in the end they are all just window messages. You can do everything in automation with the _SendMessage function, provided you know what you're doing.
Certain designs and interfaces make it very difficult, if not virtually impossible, for AutoIt to tap into the interface to read control information. I would suggest either using the WLM protocol manually via your own client, or utilize a client that doesn't make screen grabbing the text hard or impossible.
Ok, maybe finally an answer... at least this test app I coded works as following:
Somewhere in the beginning of your script you have to set the state of your WLM to #SW_HIDE. Later when you try to do ControlXxxx-stuff you first set a variable on your active window. Now you can optionally block your input and activate your hidden window. It now works as you described above and afterwards you reactivate your last active window. Optionally undo the input block again.
That should solve your question with the least breaktime... you could play with your Mouse Cursor Style in the meantime to simulate some CPU load, so the block input is not too offending. But the action is so fast you won't even recognise it... (maybe it will swallow some keypresses though)
Give it a try!
Opt("WinTitleMatchMode", 2)
#include <GuiConstantsEx.au3>
$GUI = GUICreate("Beispiel HiddenApp", 392, 323)
$ed = GUICtrlCreateEdit("nix", 1, 1, 390, 321)
GUISetState()
Sleep(1000)
GUISetState(#SW_HIDE, $GUI)
WinActivate("SciTE")
Sleep(1000)
BlockInput(1)
$act = WinActive("[ACTIVE]")
WinActivate($GUI)
ControlClick($GUI, "", $ed, "primary", 1, 50, 50)
ControlSend($GUI, "", $ed, "before{Alt}{Tab}after")
WinActivate($act)
BlockInput(0)
Sleep(1000)
GUISetState(#SW_SHOW, $GUI)
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
ExitLoop
Case Else
;;;
EndSwitch
WEnd