/*
 * MACDRV Cocoa event queue code
 *
 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <libkern/OSAtomic.h>
#import <Carbon/Carbon.h>

#include "macdrv_cocoa.h"
#import "cocoa_event.h"
#import "cocoa_app.h"
#import "cocoa_window.h"


static NSString* const WineEventQueueThreadDictionaryKey = @"WineEventQueueThreadDictionaryKey";

static NSString* const WineHotKeyMacIDKey       = @"macID";
static NSString* const WineHotKeyVkeyKey        = @"vkey";
static NSString* const WineHotKeyModFlagsKey    = @"modFlags";
static NSString* const WineHotKeyKeyCodeKey     = @"keyCode";
static NSString* const WineHotKeyCarbonRefKey   = @"hotKeyRef";
static const OSType WineHotKeySignature = 'Wine';


@implementation NSEvent (WineExtensions)

    static BOOL wine_commandKeyDown(NSUInteger flags)
    {
        return ((flags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)) == NSCommandKeyMask);
    }

    + (BOOL) wine_commandKeyDown
    {
        return wine_commandKeyDown([self modifierFlags]);
    }

    - (BOOL) wine_commandKeyDown
    {
        return wine_commandKeyDown([self modifierFlags]);
    }

@end


@interface MacDrvEvent : NSObject
{
@public
    macdrv_event* event;
}

    - (id) initWithEvent:(macdrv_event*)event;

@end

@implementation MacDrvEvent

    - (id) initWithEvent:(macdrv_event*)inEvent
    {
        self = [super init];
        if (self)
        {
            event = macdrv_retain_event(inEvent);
        }
        return self;
    }

    - (void) dealloc
    {
        if (event) macdrv_release_event(event);
        [super dealloc];
    }

@end


@implementation WineEventQueue

    - (id) init
    {
        [self doesNotRecognizeSelector:_cmd];
        [self release];
        return nil;
    }

    - (id) initWithEventHandler:(macdrv_event_handler)handler
    {
        NSParameterAssert(handler != nil);

        self = [super init];
        if (self != nil)
        {
            struct kevent kev;
            int rc;

            fds[0] = fds[1] = kq = -1;

            event_handler = handler;
            events = [[NSMutableArray alloc] init];
            eventsLock = [[NSLock alloc] init];

            if (!events || !eventsLock)
            {
                [self release];
                return nil;
            }

            if (pipe(fds) ||
                fcntl(fds[0], F_SETFD, 1) == -1 ||
                fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
                fcntl(fds[1], F_SETFD, 1) == -1 ||
                fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1)
            {
                [self release];
                return nil;
            }

            kq = kqueue();
            if (kq < 0)
            {
                [self release];
                return nil;
            }

            EV_SET(&kev, fds[0], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
            do
            {
                rc = kevent(kq, &kev, 1, NULL, 0, NULL);
            } while (rc == -1 && errno == EINTR);
            if (rc == -1)
            {
                [self release];
                return nil;
            }
        }
        return self;
    }

    - (void) dealloc
    {
        NSNumber* hotKeyMacID;

        for (hotKeyMacID in hotKeysByMacID)
        {
            NSDictionary* hotKeyDict = [hotKeysByMacID objectForKey:hotKeyMacID];
            EventHotKeyRef hotKeyRef = [[hotKeyDict objectForKey:WineHotKeyCarbonRefKey] pointerValue];
            UnregisterEventHotKey(hotKeyRef);
        }
        [hotKeysByMacID release];
        [hotKeysByWinID release];
        [events release];
        [eventsLock release];

        if (kq != -1) close(kq);
        if (fds[0] != -1) close(fds[0]);
        if (fds[1] != -1) close(fds[1]);

        [super dealloc];
    }

    - (void) signalEventAvailable
    {
        char junk = 1;
        int rc;

        do
        {
            rc = write(fds[1], &junk, 1);
        } while (rc < 0 && errno == EINTR);

        if (rc < 0 && errno != EAGAIN)
            ERR(@"%@: got error writing to event queue signaling pipe: %s\n", self, strerror(errno));
    }

    - (void) postEventObject:(MacDrvEvent*)event
    {
        NSIndexSet* indexes;
        MacDrvEvent* lastEvent;

        [eventsLock lock];

        indexes = [events indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
            return ((MacDrvEvent*)obj)->event->deliver <= 0;
        }];
        [events removeObjectsAtIndexes:indexes];

        if ((event->event->type == MOUSE_MOVED ||
             event->event->type == MOUSE_MOVED_ABSOLUTE) &&
            event->event->deliver == INT_MAX &&
            (lastEvent = [events lastObject]) &&
            (lastEvent->event->type == MOUSE_MOVED ||
             lastEvent->event->type == MOUSE_MOVED_ABSOLUTE) &&
            lastEvent->event->deliver == INT_MAX &&
            lastEvent->event->window == event->event->window &&
            lastEvent->event->mouse_moved.drag == event->event->mouse_moved.drag)
        {
            if (event->event->type == MOUSE_MOVED)
            {
                lastEvent->event->mouse_moved.x += event->event->mouse_moved.x;
                lastEvent->event->mouse_moved.y += event->event->mouse_moved.y;
            }
            else
            {
                lastEvent->event->type = MOUSE_MOVED_ABSOLUTE;
                lastEvent->event->mouse_moved.x = event->event->mouse_moved.x;
                lastEvent->event->mouse_moved.y = event->event->mouse_moved.y;
            }

            lastEvent->event->mouse_moved.time_ms = event->event->mouse_moved.time_ms;
        }
        else
            [events addObject:event];

        [eventsLock unlock];

        [self signalEventAvailable];
    }

    - (void) postEvent:(macdrv_event*)inEvent
    {
        MacDrvEvent* event = [[MacDrvEvent alloc] initWithEvent:inEvent];
        [self postEventObject:event];
        [event release];
    }

    - (MacDrvEvent*) getEventMatchingMask:(macdrv_event_mask)mask
    {
        char buf[512];
        int rc;
        NSUInteger index;
        MacDrvEvent* ret = nil;

        /* Clear the pipe which signals there are pending events. */
        do
        {
            rc = read(fds[0], buf, sizeof(buf));
        } while (rc > 0 || (rc < 0 && errno == EINTR));
        if (rc == 0 || (rc < 0 && errno != EAGAIN))
        {
            if (rc == 0)
                ERR(@"%@: event queue signaling pipe unexpectedly closed\n", self);
            else
                ERR(@"%@: got error reading from event queue signaling pipe: %s\n", self, strerror(errno));
            return nil;
        }

        [eventsLock lock];

        index = 0;
        while (index < [events count])
        {
            MacDrvEvent* event = [events objectAtIndex:index];
            if (event_mask_for_type(event->event->type) & mask)
            {
                [[event retain] autorelease];
                [events removeObjectAtIndex:index];

                if (event->event->deliver == INT_MAX ||
                    OSAtomicDecrement32Barrier(&event->event->deliver) >= 0)
                {
                    ret = event;
                    break;
                }
            }
            else
                index++;
        }

        [eventsLock unlock];
        return ret;
    }

    - (void) discardEventsPassingTest:(BOOL (^)(macdrv_event* event))block
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        NSIndexSet* indexes;

        [eventsLock lock];

        indexes = [events indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
            MacDrvEvent* event = obj;
            return block(event->event);
        }];

        [events removeObjectsAtIndexes:indexes];

        [eventsLock unlock];

        [pool release];
    }

    - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)window
    {
        [self discardEventsPassingTest:^BOOL (macdrv_event* event){
            return ((event_mask_for_type(event->type) & mask) &&
                    (!window || event->window == (macdrv_window)window));
        }];
    }

    - (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout flags:(NSUInteger)flags
    {
        int type;
        macdrv_event* event;
        NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
        BOOL timedout;

        type = (flags & WineQueryNoPreemptWait) ? QUERY_EVENT_NO_PREEMPT_WAIT : QUERY_EVENT;
        event = macdrv_create_event(type, (WineWindow*)query->window);
        event->query_event.query = macdrv_retain_query(query);
        query->done = FALSE;

        [self postEvent:event];
        macdrv_release_event(event);
        timedout = ![[WineApplicationController sharedController] waitUntilQueryDone:&query->done
                                                                             timeout:timeoutDate
                                                                       processEvents:(flags & WineQueryProcessEvents) != 0];
        return !timedout && query->status;
    }

    - (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout
    {
        return [self query:query timeout:timeout flags:0];
    }

    - (void) resetMouseEventPositions:(CGPoint)pos
    {
        MacDrvEvent* event;

        pos = cgpoint_win_from_mac(pos);

        [eventsLock lock];

        for (event in events)
        {
            if (event->event->type == MOUSE_BUTTON)
            {
                event->event->mouse_button.x = pos.x;
                event->event->mouse_button.y = pos.y;
            }
            else if (event->event->type == MOUSE_SCROLL)
            {
                event->event->mouse_scroll.x = pos.x;
                event->event->mouse_scroll.y = pos.y;
            }
        }

        [eventsLock unlock];
    }

    - (BOOL) postHotKeyEvent:(UInt32)hotKeyNumber time:(double)time
    {
        NSDictionary* hotKeyDict = [hotKeysByMacID objectForKey:[NSNumber numberWithUnsignedInt:hotKeyNumber]];
        if (hotKeyDict)
        {
            macdrv_event* event;

            event = macdrv_create_event(HOTKEY_PRESS, nil);
            event->hotkey_press.vkey        = [[hotKeyDict objectForKey:WineHotKeyVkeyKey] unsignedIntValue];
            event->hotkey_press.mod_flags   = [[hotKeyDict objectForKey:WineHotKeyModFlagsKey] unsignedIntValue];
            event->hotkey_press.keycode     = [[hotKeyDict objectForKey:WineHotKeyKeyCodeKey] unsignedIntValue];
            event->hotkey_press.time_ms     = [[WineApplicationController sharedController] ticksForEventTime:time];

            [self postEvent:event];

            macdrv_release_event(event);
        }

        return hotKeyDict != nil;
    }

    static OSStatus HotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
    {
        WineEventQueue* self = userData;
        OSStatus status;
        EventHotKeyID hotKeyID;

        status = GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL,
                                   sizeof(hotKeyID), NULL, &hotKeyID);
        if (status == noErr)
        {
            if (hotKeyID.signature != WineHotKeySignature ||
                ![self postHotKeyEvent:hotKeyID.id time:GetEventTime(theEvent)])
                status = eventNotHandledErr;
        }

        return status;
    }

    - (void) unregisterHotKey:(unsigned int)vkey modFlags:(unsigned int)modFlags
    {
        NSNumber* vkeyNumber = [NSNumber numberWithUnsignedInt:vkey];
        NSNumber* modFlagsNumber = [NSNumber numberWithUnsignedInt:modFlags];
        NSArray* winIDPair = [NSArray arrayWithObjects:vkeyNumber, modFlagsNumber, nil];
        NSDictionary* hotKeyDict = [hotKeysByWinID objectForKey:winIDPair];
        if (hotKeyDict)
        {
            EventHotKeyRef hotKeyRef = [[hotKeyDict objectForKey:WineHotKeyCarbonRefKey] pointerValue];
            NSNumber* macID = [hotKeyDict objectForKey:WineHotKeyMacIDKey];

            UnregisterEventHotKey(hotKeyRef);
            [hotKeysByMacID removeObjectForKey:macID];
            [hotKeysByWinID removeObjectForKey:winIDPair];
        }
    }

    - (int) registerHotKey:(UInt32)keyCode modifiers:(UInt32)modifiers vkey:(unsigned int)vkey modFlags:(unsigned int)modFlags
    {
        static EventHandlerRef handler;
        static UInt32 hotKeyNumber;
        OSStatus status;
        NSNumber* vkeyNumber;
        NSNumber* modFlagsNumber;
        NSArray* winIDPair;
        EventHotKeyID hotKeyID;
        EventHotKeyRef hotKeyRef;
        NSNumber* macIDNumber;
        NSDictionary* hotKeyDict;

        if (!handler)
        {
            EventTypeSpec eventType = { kEventClassKeyboard, kEventHotKeyPressed };
            status = InstallApplicationEventHandler(HotKeyHandler, 1, &eventType, self, &handler);
            if (status != noErr)
            {
                ERR(@"InstallApplicationEventHandler() failed: %d\n", status);
                handler = NULL;
                return MACDRV_HOTKEY_FAILURE;
            }
        }

        if (!hotKeysByMacID && !(hotKeysByMacID = [[NSMutableDictionary alloc] init]))
            return MACDRV_HOTKEY_FAILURE;
        if (!hotKeysByWinID && !(hotKeysByWinID = [[NSMutableDictionary alloc] init]))
            return MACDRV_HOTKEY_FAILURE;

        vkeyNumber = [NSNumber numberWithUnsignedInt:vkey];
        modFlagsNumber = [NSNumber numberWithUnsignedInt:modFlags];
        winIDPair = [NSArray arrayWithObjects:vkeyNumber, modFlagsNumber, nil];
        if ([hotKeysByWinID objectForKey:winIDPair])
            return MACDRV_HOTKEY_ALREADY_REGISTERED;

        hotKeyID.signature  = WineHotKeySignature;
        hotKeyID.id         = hotKeyNumber++;

        status = RegisterEventHotKey(keyCode, modifiers, hotKeyID, GetApplicationEventTarget(),
                                     kEventHotKeyExclusive, &hotKeyRef);
        if (status == eventHotKeyExistsErr)
            return MACDRV_HOTKEY_ALREADY_REGISTERED;
        if (status != noErr)
        {
            ERR(@"RegisterEventHotKey() failed: %d\n", status);
            return MACDRV_HOTKEY_FAILURE;
        }

        macIDNumber = [NSNumber numberWithUnsignedInt:hotKeyID.id];
        hotKeyDict = [NSDictionary dictionaryWithObjectsAndKeys:
                      macIDNumber, WineHotKeyMacIDKey,
                      vkeyNumber, WineHotKeyVkeyKey,
                      modFlagsNumber, WineHotKeyModFlagsKey,
                      [NSNumber numberWithUnsignedInt:keyCode], WineHotKeyKeyCodeKey,
                      [NSValue valueWithPointer:hotKeyRef], WineHotKeyCarbonRefKey,
                      nil];
        [hotKeysByMacID setObject:hotKeyDict forKey:macIDNumber];
        [hotKeysByWinID setObject:hotKeyDict forKey:winIDPair];

        return MACDRV_HOTKEY_SUCCESS;
    }


/***********************************************************************
 *              OnMainThread
 *
 * Run a block on the main thread synchronously.
 */
void OnMainThread(dispatch_block_t block)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];
    WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey];
    dispatch_semaphore_t semaphore = NULL;
    __block BOOL finished;

    if (!queue)
    {
        semaphore = dispatch_semaphore_create(0);
        dispatch_retain(semaphore);
    }

    finished = FALSE;
    OnMainThreadAsync(^{
        block();
        finished = TRUE;
        if (queue)
            [queue signalEventAvailable];
        else
        {
            dispatch_semaphore_signal(semaphore);
            dispatch_release(semaphore);
        }
    });

    if (queue)
    {
        while (!finished)
        {
            MacDrvEvent* macDrvEvent;
            struct kevent kev;

            while (!finished &&
                   (macDrvEvent = [queue getEventMatchingMask:event_mask_for_type(QUERY_EVENT)]))
            {
                queue->event_handler(macDrvEvent->event);
            }

            if (!finished)
            {
                [pool release];
                pool = [[NSAutoreleasePool alloc] init];

                kevent(queue->kq, NULL, 0, &kev, 1, NULL);
            }
        }
    }
    else
    {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_release(semaphore);
    }

    [pool release];
}


/***********************************************************************
 *              macdrv_create_event_queue
 *
 * Register this thread with the application on the main thread, and set
 * up an event queue on which it can deliver events to this thread.
 */
macdrv_event_queue macdrv_create_event_queue(macdrv_event_handler handler)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];

    WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey];
    if (!queue)
    {
        queue = [[[WineEventQueue alloc] initWithEventHandler:handler] autorelease];
        if (queue)
        {
            if ([[WineApplicationController sharedController] registerEventQueue:queue])
                [threadDict setObject:queue forKey:WineEventQueueThreadDictionaryKey];
            else
                queue = nil;
        }
    }

    [pool release];
    return (macdrv_event_queue)queue;
}

/***********************************************************************
 *              macdrv_destroy_event_queue
 *
 * Tell the application that this thread is exiting and destroy the
 * associated event queue.
 */
void macdrv_destroy_event_queue(macdrv_event_queue queue)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    WineEventQueue* q = (WineEventQueue*)queue;
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];

    [[WineApplicationController sharedController] unregisterEventQueue:q];
    [threadDict removeObjectForKey:WineEventQueueThreadDictionaryKey];

    [pool release];
}

/***********************************************************************
 *              macdrv_get_event_queue_fd
 *
 * Get the file descriptor whose readability signals that there are
 * events on the event queue.
 */
int macdrv_get_event_queue_fd(macdrv_event_queue queue)
{
    WineEventQueue* q = (WineEventQueue*)queue;
    return q->fds[0];
}

/***********************************************************************
 *              macdrv_copy_event_from_queue
 *
 * Pull an event matching the event mask from the event queue and store
 * it in the event record pointed to by the event parameter.  If a
 * matching event was found, return non-zero; otherwise, return 0.
 *
 * The caller is responsible for calling macdrv_release_event on any
 * event returned by this function.
 */
int macdrv_copy_event_from_queue(macdrv_event_queue queue,
        macdrv_event_mask mask, macdrv_event **event)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    WineEventQueue* q = (WineEventQueue*)queue;

    MacDrvEvent* macDrvEvent = [q getEventMatchingMask:mask];
    if (macDrvEvent)
        *event = macdrv_retain_event(macDrvEvent->event);

    [pool release];
    return (macDrvEvent != nil);
}

/***********************************************************************
 *              macdrv_create_event
 */
macdrv_event* macdrv_create_event(int type, WineWindow* window)
{
    macdrv_event *event;

    event = calloc(1, sizeof(*event));
    event->refs = 1;
    event->deliver = INT_MAX;
    event->type = type;
    event->window = (macdrv_window)[window retain];
    return event;
}

/***********************************************************************
 *              macdrv_retain_event
 */
macdrv_event* macdrv_retain_event(macdrv_event *event)
{
    OSAtomicIncrement32Barrier(&event->refs);
    return event;
}

/***********************************************************************
 *              macdrv_release_event
 *
 * Decrements the reference count of an event.  If the count falls to
 * zero, cleans up any resources, such as allocated memory or retained
 * objects, held by the event and deallocates it
 */
void macdrv_release_event(macdrv_event *event)
{
    if (OSAtomicDecrement32Barrier(&event->refs) <= 0)
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        switch (event->type)
        {
            case IM_SET_TEXT:
                if (event->im_set_text.text)
                    CFRelease(event->im_set_text.text);
                break;
            case KEYBOARD_CHANGED:
                CFRelease(event->keyboard_changed.uchr);
                CFRelease(event->keyboard_changed.input_source);
                break;
            case QUERY_EVENT:
            case QUERY_EVENT_NO_PREEMPT_WAIT:
                macdrv_release_query(event->query_event.query);
                break;
            case WINDOW_GOT_FOCUS:
                [(NSMutableSet*)event->window_got_focus.tried_windows release];
                break;
        }

        [(WineWindow*)event->window release];
        free(event);

        [pool release];
    }
}

/***********************************************************************
 *              macdrv_create_query
 */
macdrv_query* macdrv_create_query(void)
{
    macdrv_query *query;

    query = calloc(1, sizeof(*query));
    query->refs = 1;
    return query;
}

/***********************************************************************
 *              macdrv_retain_query
 */
macdrv_query* macdrv_retain_query(macdrv_query *query)
{
    OSAtomicIncrement32Barrier(&query->refs);
    return query;
}

/***********************************************************************
 *              macdrv_release_query
 */
void macdrv_release_query(macdrv_query *query)
{
    if (OSAtomicDecrement32Barrier(&query->refs) <= 0)
    {
        switch (query->type)
        {
            case QUERY_DRAG_OPERATION:
                if (query->drag_operation.pasteboard)
                    CFRelease(query->drag_operation.pasteboard);
                break;
            case QUERY_DRAG_DROP:
                if (query->drag_drop.pasteboard)
                    CFRelease(query->drag_drop.pasteboard);
                break;
            case QUERY_PASTEBOARD_DATA:
                if (query->pasteboard_data.type)
                    CFRelease(query->pasteboard_data.type);
                break;
        }
        [(WineWindow*)query->window release];
        free(query);
    }
}

/***********************************************************************
 *              macdrv_set_query_done
 */
void macdrv_set_query_done(macdrv_query *query)
{
    macdrv_retain_query(query);

    OnMainThreadAsync(^{
        NSEvent* event;

        query->done = TRUE;
        macdrv_release_query(query);

        event = [NSEvent otherEventWithType:NSApplicationDefined
                                   location:NSZeroPoint
                              modifierFlags:0
                                  timestamp:[[NSProcessInfo processInfo] systemUptime]
                               windowNumber:0
                                    context:nil
                                    subtype:WineApplicationEventWakeQuery
                                      data1:0
                                      data2:0];
        [NSApp postEvent:event atStart:TRUE];
    });
}

@end


/***********************************************************************
 *              macdrv_register_hot_key
 */
int macdrv_register_hot_key(macdrv_event_queue q, unsigned int vkey, unsigned int mod_flags,
                            unsigned int keycode, unsigned int modifiers)
{
    WineEventQueue* queue = (WineEventQueue*)q;
    __block int ret;

    OnMainThread(^{
        ret = [queue registerHotKey:keycode modifiers:modifiers vkey:vkey modFlags:mod_flags];
    });

    return ret;
}


/***********************************************************************
 *              macdrv_unregister_hot_key
 */
void macdrv_unregister_hot_key(macdrv_event_queue q, unsigned int vkey, unsigned int mod_flags)
{
    WineEventQueue* queue = (WineEventQueue*)q;

    OnMainThreadAsync(^{
        [queue unregisterHotKey:vkey modFlags:mod_flags];
    });
}
