Question
How to use these private functions on other windows? It would be nice to have this knowledge back in the wild. I am specifically trying to get CGSOrderWindow and CGSSetWindowLevel to work.
I was trying in the direction of:
temporarily register as the dock and then register the dock as the dock again immediately afterwards
or
code injection into the Dock process per this comment:
Also, the author of the above project seems determined to make all core functionality available as a framework. It seems to be implemented as code injection into the Dock process.
Reason I know this is possible
I have been doing work on trying to setLevel on window of another app, and focus window of another app if focused. I am posting this again with the info I learned because from my searching online, I know this was done in the past, its just the knowledge is not publicly out there anymore. The sourceforge pages are no longer there. So I was wondering if you could help me make this information public again.
This is the topic I read that gave me this information - http://cocoadev.com/HowtoControlOtherAppsWindows
Here you see comments like:
You cannot control an another app's windows from a user-level process, unfortunately.
SlavaKarpenko
You can, Slava, you just need to register as the Dock. It might be possible to temporarily register as the dock and then register the dock as the dock again immediately afterwards, not sure. I think the call you'd be wanting to investigate as CoreDockRegisterDockOwner in HIServices.framework.
FinlayDobbie
You could also use APE or similar to do control the windows, or (as mentioned above) register as the Dock (look for the private APIs with Universal Connection in their name). Has anyone found a polite way of getting the Dock to give up its universal connection? The only way I can find is to force quit the Dock and grab the universal connection when it's not looking (which prevents the dock reloading).
SamTaylor
There's an open source project up on sourceforge.net that looks much more like the window managers I've used on Unix boxes than Space.app (or Space.dock): http://wsmanager.sourceforge.net/
SteveCook
Verifying things work
This is what I learned, from the sources at bottom of this post, we see all these functions work with CGWindowIds, so how do I get that, this is how:
Get all windows with CGWindowListCopyWindowInfo. Then access each element from that array with CFArrayGetValueAtIndex and then get the CGWindowId with objectForKey:, kCGWindowNumber, and then integerValue.
Now if I try to focus or set level of a window that is OWNED by the app running the code, it works fantastic. For instance:
MY_TARGET_CGWINDOW_ID = 179;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID, kCGSOrderAbove, 0);
Will focus it, rez_CGError is 0. Even if the window is minimized, it is unminimized, without animation, and shown.
Now however, if I try this on a window of a different app we get some errors:
MY_TARGET_CGWINDOW_ID_of_other_app = 40;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);
This fails and rez_CGError is 1000, which I suspect means "cid (CGSConnection) used does not have permission to modify target window". The same happens if I first do [app activateWithOptions: (NSApplicationActivateIgnoringOtherApps | NSApplicationActivateAllWindows)] before making the call above.
So I first get the cid of that owning window like this:
var rez_CGError = CGSGetWindowOwner(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, &ownerCid);
This works good and I get ownerCid is set to a value. Then I do the focus command with this new connection:
rez_CGError = CGSOrderWindow(ownerCid, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);
However this gives rez_CGError of 268435459, which I suspect means "current app does not have permission to use this ConnectionId (cid)". (Same happens if I call activateWithOptions first.
My Sources for the Private Functions
Here is the sources for some private functions I found - https://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h
This one source here contains a function that is not in the above link - CGSGetConnectionIDForPSN - i test it and it exists - from - https://github.com/mnutt/libqxt/blob/767498816dfa1742a6f3aee787281745afec11b8/src/gui/qxtwindowsystem_mac.h#L80
Related
I have made a custom virtual keyboard widget for my kiosk application, and now comes the time when I want it to produce fake keyboard events and feed them to an QLineEdit of choice.
I do the following:
// target is the QWidget to receive the events
// k is the Qt::Key (keycode) I want to send (Testing with an 'A')
Qt::Key k=Qt::Key_A;
if(0!=target){
//According to docs this will be freed once posted
QKeyEvent * press=new QKeyEvent(QKeyEvent::KeyPress, (int )k,0);
QKeyEvent * release=new QKeyEvent(QKeyEvent::KeyRelease, (int )k,0);
//Give the target focus just to be sure it is available for input
target->setFocus();
//Post the events (queue up and let the target consume them when the eventloop gets around to the target)
QCoreApplication::postEvent ( target, press) ;
QCoreApplication::postEvent ( target, release) ;
}
I see the target widget receive focus, but there are no letters typed into the input field like I would expect. What am I doing wrong? Which assumptions are wrong?
PS: I know that this could be solved by using existing virtual keyboards or at least using the platform interface as is done in this post. In our approach we have decided to build the kayboard into the application to obtain full control over the UX and keyboard design.
Thanks!
Since no-one stepped up, I will try to provide some closure.
It turns out that Qt5 comes with a library of testing facilities called testlib. It has all sorts of goodies to facilitate easy creation, management and running of unit tests for Qt application. Among these facilities there is a set of functions for sending fake events such as fake typing of text, mouse clicks etc. It is quite comprehensive and covers many use-cases. Since this is used internally by Qt developers to test Qt itself it is also production proven code.
I simply copied what I needed from there.
So i have a titanium app, and i just read about single contexts. (Incidentally, somebody here should write a book about programming in titanium... the only one out there doesn't really mention single contexts or any of that new-fangled stuff. Heck, make it an eBook. I'd buy it)
The titanium documentation stresses their use (http://docs.appcelerator.com/titanium/latest/#!/guide/Coding_Strategies-section-29004891_CodingStrategies-Executioncontexts) and then politely forgets how to implement a single context!!
So, question:
Let's say i have the awesomeWidget page - this just shows a button, and when you click on a button a new screen appears.
The aswesomeWidget page is accessed through another page - it is not from the root of the titanium app.
Keeping to single contexts, how do i add the view that the button creates to the current window?
Do I:
keep a global pointer to the current (and only) window?
pass the variable holding the current window down to all the following pages that use it
something else?
First off, Titanium keeps a reference to your current window anyway for you, so this use case is easy. For example:
awesomeWidgetButton.addEventListener('click' function(e) {
var yourView = Ti.UI.createView({...});
Titanium.UI.currentWindow.add(yourView);
});
If you want to dig further, the concept of a single context is closely tied to the use of CommonJS modules and the require keyword. It is very simple to keep a single context, just never open a window with the url component filled out, and liberally use the require() keyword. Other than that, its up to your imagination to keep track of who points to what and vice versa, there are standard patterns and best practices that apply here (MVC, Singletons, just keep it simple) just as in coding in any other language.
I have console applicaiotn that currently uses CAsyncSocket.
I need to implement SSL so after some searching I found this project: http://www.codeproject.com/Articles/3915/CAsyncSslSocketLayer-SSL-layer-class-for-CAsyncSoc
For some reason same simple code that works fine on GUI code does not work in console app.
Has anyone exp. with CAsyncSslSocketLayer ?
Thanks.
CAsyncSocketEx uses a window as a sort of cheap thread to handle the event notifications that come from select(). Unfortunately, if you don't have a message loop, then the window which it creates will not receive these events.
http://support.microsoft.com/kb/90975
This article explains that a call to CreateWindow() needs to be called from a thread which has a message loop. And if you don't, then anything sent via PostMessage() won't get there.
I've recently started to tinker with this -- I want to remove the annoying hidden window and replace it with a normal thread. Their code relies on WSAAsyncSelect() in order to receive socket events... to a window. Yuk!
It's been a while since I had the same problem, but if I remember correctly, to use CAsyncSocket in a console app you need to add something like DECLARE_CONSOLEAPP (first two links shown below) to your console app. This should give your console a message pump to generate the socket notifications (OnReceive, etc.) GUI apps have these pumps but console apps don't, generally. The third (msdn) link below might also apply, it has more info and a different way.
If these still don't work, you should put breakpoints in your socket code and make sure your socket isn't instantiated in a thread or callback other than the main console app (the one that now has the message pump).
I think googling around for 'CAsyncSocket WinApp' or 'CAsyncSocket console app' would show more.
http://www.codeguru.com/cpp/misc/misc/consoleapps/article.php/c243/Console-app-using-MFC.htm
http://troels.knakkergaard.dk/code.htm
http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/a6f1b72a-21d8-4046-a3dc-d7d29ece2ef6
I’m looking for alternative for existing tests written in QTP for my Win32 application written in Borland C++.
My candidate is White which based on UI Automation because it’s native solution,
I can create my tests using .NET/C# and easily integrate it with nUnit and Hudson.
White
http://white.codeplex.com
MS UI Automation
http://msdn.microsoft.com/en-us/library/ms747327.aspx
UI Verify
http://uiautomationverify.codeplex.com
I use UI Verify as a spy to identify properties of objects I want to find in my tests.
More or less when I can see something in the spy, I can find it using UI Automation/White.
Generally I don't have much problems with recognizing objects
but when I try to search some content inside the tab contained in Tab Panel
or try to see MenuItems of Menu bar then the problem appears.
UI Automation/UI Verify works wired. When I run UI Verify (1.0 version) I see that objects can be registered properly only then
when I set 'Focus tracking' option and click on target objects or change the keyboard cursor on them. Otherwise it's impossible to find them.
UI Verifier can show me children of my 'tab' panel then. But I can’t find them using UI Automation/White. This is example code:
Tab tab = window.Get();
ITabPage tabPage = tab.SelectedTab;
AutomationElementCollection newCol = tabPage.AutomationElement.FindAll(TreeScope.Descendants, Condition.TrueCondition);
window.Get("buttonName");
the collection is empty even though spy see the children.
Does any of you have some experience with White/UI Automation library that he/she would like to share with me?
I want to implement the tracking feature from the spy to my tests. Can you help me with that? I'm trying to study the code of UIA Verify spy. I think that there are two classes responsible for catching the objects: FocusChangeListener and FocusTracer - this is the code:
http://uiautomationverify.codeplex.com/SourceControl/changeset/view/9992#214260
http://uiautomationverify.codeplex.com/SourceControl/changeset/view/9992#214192
Requirements:
1. Windows SDK
2. .NET 3.5
3. White
4. UIA Verify code
Do you have any better alternative for White/UI Automation?
R.
Could you, the R or YoYo, put your form compiled or in source codes (preferable without the internal logic) somewhere on a file share?
I've never seen a control that'd be not caught using UI Automation if UIAVerify sees it. I saw such windows, which could be only caught with the Focus Tracking feature of UIAVerify. This case, such a window is untouchable by UI Automation search.
Regarding a control, are you sure that the controls you struggling with have the Name property? Maybe, this is a value available only by means of ValuePattern, not the Name?
It is quite tricky because I wanna to take the result as a sign for later process. If a window flashes, it would be weird to user.
(This is not an answer, just refreshing the question and adding some details:)
Suppose you need to open a video capture driver (webcam) with code like this (delphi, but easy understandable):
result:= SendMessage(hCapWnd, WM_CAP_DRIVER_CONNECT, FDriverNo, 0);
It works fine, except when camera/webcam is busy (opened by another application, for example moviemaker). Then the capture driver suddenly shows a "select video source" window that blocks your application (but not moviemaker, which keeps recording). SendMessage function becomes modal and will not return until undesired window is closed.
Is there a way to detect if a capture driver is busy with another application before connecting to it?
Thanks
This function return number of available webcams and scanners on your mashine(с++).
int GetNumCam()
{
int MemberIndex = 0;
HDEVINFO dev;
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
dev = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_IMAGE, NULL,NULL,DIGCF_PRESENT);
if (dev == NULL)
{
MessageBoxA(0,"it is null..","vse propalo",0);
return -1;
}
else
{
while(SetupDiEnumDeviceInfo(dev,MemberIndex, &DeviceInfoData))
{
MemberIndex++;
}
}
return MemberIndex;
}
I wonder if sending a broadcast message could do. I mean, suppose you send a VFW info request message to all windows in system. Then, all windows actually doing VFW processing will answer their status info and you will know which of them are doing video processing; some kind of shouting "anybody here...?"
But it looks like brute force, or even hacking. May be I'll test it... may be not. I am sure there must be a smarter way to know if a video capture driver is busy with another application.
(btw... anybody here?)
I was afraid it would happen.
First I enumerated all opened windows in system, then executed this instruction for each HWND, which just asks for driver information (pascal syntax):
SendMessage(h, WM_CAP_DRIVER_GET_NAME, length(driver)*sizeof(char), LPARAM(PChar(driver))
According to Msdn help, WM_CAP_DRIVER_GET_NAME results are:
"Returns TRUE if successful or FALSE if the capture window is not connected to a capture driver"
(Bold is mine). So it appears a good way to know:
1-If the window is capturing. So it is applyable to ALL windows, don't matter if they are capturing or not.
2-And if so, it tells you which driver is using.
However, after first test round, the results were:
- Task Manager (it was running) crashed and closed
- Explorer crashed and closed (reopened again automatically)
- Belkin Wireless monitor (my pc's WiFi driver) crashed and closed
- Eset Nod32 antivirus crashed, did not closed
The first conclussion can be that this is a bad way to locate which applications are capturing video in a system. But I must ensure to dismiss the possibility of a bug.
I'll keep reporting.
This is not a good solution my any means but I found out that if you disable and enable the camera in device manager immediately before sending the WM_CAP_DRIVER_CONNECT message then for some reason the video source window does not appear and the function returns and works OK.
So for a script I was working on I had to download devcon.exe and I put "devcon disable *PID_3450*MI_00*" and "devcon enable *PID_3450*MI_00*" immediately before my WM_CAP_DRIVER_CONNECT and it seems to work consistently. Unfortunately you need to run as administrator to be able to disable/enable devices. Again not a proper fix by any means...
(Hardware ID of my cam is USB\VID_0AC8&PID_3450&MI_00)