How to discard command+shift+Q command in mac OS X objective c code? - objective-c

I'm trying to implement a screensaver simulator on Mac OS X , I managed to disable the effect of pressing command+Q that was causing the application to exit, so now if it's in the full screen mode, it will not respond to the quit keyboard shortcut.
But, my problem is in handling the shortcut of ( Command+ Shift+Q) that pops up the confirmation dialog of Max OS X that warns exiting all the apps and logging of the system.
Can anyone help me in preventing the effect of command+shift+q shortcut while being in full screen mode ?
thanks

This is the best answer for this question
First in your applicationDidFinishedLoad function, add this peace of code to create an event tap and add the event tap in the current run loop
CFMachPortRef eventTap;
CGEventMask eventMask;
CFRunLoopSourceRef runLoopSource;
// Create an event tap. We are interested in key presses.
eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
eventMask, myCGEventCallback, NULL);
if (!eventTap) {
fprintf(stderr, "failed to create event tap\n");
exit(1);
}
// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(
kCFAllocatorDefault, eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
kCFRunLoopCommonModes);
// Enable the event tap.
CGEventTapEnable(eventTap, true);
then in your class, you can implement the call back function called myCGEventCallback like this
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
CGEventRef event, void *refcon)
{
// Paranoid sanity check.
// type will be key down or key up, you can discard the command + q by setting the kecode to be -1 like this
if (((type == kCGEventKeyDown) || (type == kCGEventKeyUp)))
{
CGEventSetIntegerValueField(
event, kCGKeyboardEventKeycode, (int64_t)-1);
return event;
}
// The incoming keycode.
CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(
event, kCGKeyboardEventKeycode);
// Swap 'a' (keycode=0) and 'z' (keycode=6).
if (keycode == (CGKeyCode)0)
keycode = (CGKeyCode)6;
else if (keycode == (CGKeyCode)6)
keycode = (CGKeyCode)0;
// Set the modified keycode field in the event.
CGEventSetIntegerValueField(
event, kCGKeyboardEventKeycode, (int64_t)keycode);
// We must return the event for it to be useful.
return event;
}
for the original code
Check Here
Thanks

Related

macOS objective C generate keyboard events keystroke with repeat

How to generate keystroke with repeat in macOS application with objective-c?
I already manage to generate the keystroke:
CGEventRef keyup, keydown;
uint64_t keyModifier=0;
VK = kVK_RightArrow;
keyModifier = 0;
keydown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)VK, true);
CGEventSetFlags( keydown, keyModifier);
keyup = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)VK, false);
CGEventSetFlags( keyup, keyModifier);
// press the key
// forward them to the frontmost app
CGEventPostToPid (pid, keydown);
// and finally behave friendly
CFRelease(keydown);
....
// somewhere else with time delay
// release the key
// forward them to the frontmost app
CGEventPostToPid (pid, keyup);
// and finally behave friendly
CFRelease(keyup);
Using this code the equivalent keyboard right key is pressed then released, but no repeat although there is enough time between the 2 events.

SDL left mouse button event without press on startup

On the start-up of my SDL program a left mouse button event is registered without me pressing the physical left mouse button. The next physical left button press is not registered. All other keys and buttons work normal. When clicking the .exe the mouse is not located within the location of the window.
Here are the specifications of that event (taken from the SDL_Event struct):
type=1025 (SDL_MOUSEBUTTONDOWN)
timestamp=24
windowID=1
which=0
button=1 (SDL_BUTTON_LEFT)
state=1
clicks=1
x=0
y=0
I am on windows 8.1 compiling with MinGW (gcc version 4.8.1).
I have SDL version 2.0.3
This is my source code:
#include <stdio.h>
#include <SDL.h>
int main(int argc, char* argv[])
{
SDL_Window* window = NULL;
SDL_Surface* screen = NULL;
SDL_Event ev;
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0);
screen = SDL_GetWindowSurface(window);
while (1) {
while (SDL_PollEvent(&ev)) {
if (ev.type == SDL_QUIT)
return 0;
else {
if (ev.type == SDL_MOUSEBUTTONDOWN) {
if (ev.button.button == SDL_BUTTON_LEFT) {
printf("MOUSE DOWN\n");
printf("type=%d\n", ev.button.type);
printf("timestamp=%d\n", ev.button.timestamp);
printf("windowID=%d\n", ev.button.windowID);
printf("which=%d\n", ev.button.which);
printf("button=%d\n", ev.button.button);
printf("state=%d\n", ev.button.state);
printf("clicks=%d\n", ev.button.clicks);
printf("x=%d\n", ev.button.x);
printf("y=%d\n\n", ev.button.y);
}
}
}
}
SDL_UpdateWindowSurface(window);
SDL_Delay(5);
}
SDL_FreeSurface(screen);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I have tried to solve it by calling SDL_PumpEvents() and SDL_FlushEvents() and while this removed the first (erroneous) event, the second press was still not registered.
Something strange I noticed was that it worked as expected when I opened the program .exe by right clicking and then pressing 'open'.
It'd be very grateful if somebody could shed light on this issue.

How to detect a click on a form reset button from QtWebKit?

Looking at the signals in the QtWebKit API, I failed to find anything that would seem to me to be what I am looking for.
QWebView
linkClicked() seems to be the closest, but a reset button is no link, and definitely does not point to an URL.
QWebPage
I considered the following signals (judging by their name), but according to their description none of them match my purpose either: contentsChanged(), contentsChanged(), contentsChanged(), selectionChanged().
QWebFrame
None of its signals matches my purpose.
QWebElement
Here I can see how to get an object representing the button(s), but it has no signals whatsoever.
I want to catch a click in a reset button in order to store the data in the form before it gets cleared, so it can be restored later.
For now, I did manage to retrieve the buttons as a QWebElementCollection of QWebElement objects, and I can modify them, but I do not know how to get them to send a signal upon click, or something similar.
// Get reset buttons.
QWebElementCollection inputResets = mainFrame()->documentElement().findAll("input[type=reset]");
inputResets += mainFrame()->documentElement().findAll("button[type=reset]");
// Change their text (just a test).
foreach(QWebElement element, inputResets)
{
element.setPlainText("Worked!");
}
Well, I got it working with this, although I do not think it is the best approach:
bool EventFilter::eventFilter(QObject* object, QEvent* event)
{
if (event->type() == QEvent::MouseButtonRelease)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::LeftButton)
{
QWebView *view = dynamic_cast<QWebView*>(object);
QPoint pos = view->mapFromGlobal(mouseEvent->globalPos());
QWebFrame *frame = view->page()->frameAt(mouseEvent->pos());
if (frame != NULL)
{
// Get the existing reset buttons.
QWebElementCollection inputResets = frame->documentElement().findAll("input[type=reset]");
inputResets += frame->documentElement().findAll("button[type=reset]");
// Check if any of them is at the clicked position.
foreach(QWebElement element, inputResets)
{
if (element.geometry().contains(pos))
{
qDebug() << "Clicked element tag:" << element.localName();
return QObject::eventFilter(object, event);
}
}
}
}
}
return QObject::eventFilter(object, event);
}
You can probably accomplish this with Qt WebKit Bridge.

CGEventPostToPSN() not working for mouse clicking

I need to send mouse click events to an arbitrary process (not necessarily the front one) without bringing that process's window to the front.
This code works for sending a mouse click and letting the window server send it to whatever process it decides has focus:
#include <ApplicationServices/ApplicationServices.h>
int
main()
{
CGEventRef down, up;
down = CGEventCreateMouseEvent(
NULL,
kCGEventLeftMouseDown,
CGPointMake(16, 36),
kCGMouseButtonLeft
);
up = CGEventCreateMouseEvent(
NULL,
kCGEventLeftMouseUp,
CGPointMake(16, 36),
kCGMouseButtonLeft
);
CGEventPost(kCGHIDEventTap, down);
CGEventPost(kCGHIDEventTap, up);
CFRelease(down);
CFRelease(up);
return 0;
}
I can send mouse click events via CGEventPost() just fine, but that requires the target process to have focus (which I am trying to avoid).
I can send keyboard events via CGEventPostToPSN() just fine, and as far as I can tell, mouse move events work too, what I'm having trouble with is mouse down/up events.
This code (pretty much the above, the only difference being that I specify myself which process to send the events to) does not work and I don't even know how to find out where it breaks down.
#include <ApplicationServices/ApplicationServices.h>
#include <Carbon/Carbon.h> /* for ProcessSerialNumber stuff */
#include <stdio.h>
int
main()
{
ProcessSerialNumber psn;
CGEventRef down, up;
if (GetFrontProcess(&psn) != noErr) {
printf("Unable to get front process\n");
return 1;
}
down = CGEventCreateMouseEvent(
NULL,
kCGEventLeftMouseDown,
CGPointMake(16, 36),
kCGMouseButtonLeft
);
up = CGEventCreateMouseEvent(
NULL,
kCGEventLeftMouseUp,
CGPointMake(16, 36),
kCGMouseButtonLeft
);
CGEventPostToPSN(&psn, down);
CGEventPostToPSN(&psn, up);
CFRelease(down);
CFRelease(up);
return 0;
}
I've been stuck on this for a few days now, and I can't seem to figure it out. According to the documentation this is (as far as I can tell) exactly how it is supposed to be done.
I have tested this code on Snow Leopard and Lion, with the same results.
Could somebody who has had success with clicking via CGEventPostToPSN() please shed some insight on the proper way to accomplish this?

capDlgVideoSource problems with multiple webcams

I have two different webcams connected to my PC, but I have problems choosing them when running the following code. I included all the initialization routine and the last line with capDlgVideoSource call is causing only the one webcam's videosource dialog to appear instead of a list where I can choose between them. OS is WinXP SP3
//Create invisible window to hold the capture window.
hwnd = CreateWindowEx(0, _T("webcampcapwindow"), _T(""), 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, GetModuleHandle(NULL), NULL);
if( !hwnd )
throw FatalException( _T("main Capture window create failed"), _T(__FILE__), __LINE__ );
//Create capture window.
capHwnd = capCreateCaptureWindow(_T("webcampcapwindowchild"), WS_CHILD, 0, 0, 1, 1, hwnd, 1);
if( !capHwnd )
throw FatalException( _T("secondary Capture window create failed"), _T(__FILE__), __LINE__ );
CAPDRIVERCAPS caps;
if(capDriverConnect(capHwnd, 0)) {
connectedtoWc = true;
break;
}
if ( !connectedtoWc )
throw FatalException( _T("Could not connect to capture driver."), _T(__FILE__), __LINE__ );
//Attach our callback to the capture window.
if( !capSetCallbackOnVideoStream(capHwnd, videoCallback))
throw FatalException( _T("Unable to Attach our callback to the capture window."), _T(__FILE__), __LINE__ );
//Make sure we can access this object from the callback.
if(!capSetUserData(capHwnd, this))
throw FatalException( _T("Could not associate user data with capture."), _T(__FILE__), __LINE__ );
//Check everything's initialised.
caps.fCaptureInitialized = false;
if( !capDriverGetCaps(capHwnd, &caps, sizeof(CAPDRIVERCAPS)))
throw FatalException( _T("Unable to get driver caps"), _T(__FILE__), __LINE__ );
if(!caps.fCaptureInitialized)
throw FatalException( _T("Unable to initialize capture driver"), _T(__FILE__), __LINE__ );
if (caps.fHasDlgVideoSource)
capDlgVideoSource(capHwnd);
What do I change so I can get to select the webcam in video source dialog? Currently it shows the second webcam properties.
It's a bit unclear from your question, and I'm no expert, but it would appear you're using VfW, which many camera drivers don't support anymore.
Support is built in using a WDM backwards compatibility driver, which doesn't seem to work very well. The only solution I've seen to this problem is to perform some registry gymnastics (set DevicePath in HKLM\SYSTEM\CurrentControlSet\Control\MediaResources\msvideo\MSVideo.VFWWDM to the desired device), but this is a bit over my head - I'm a hardware guy.