1*4882a593Smuzhiyun/* x-input.m -- event handling 2*4882a593Smuzhiyun * 3*4882a593Smuzhiyun * Copyright (c) 2002-2012 Apple Inc. All rights reserved. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person 6*4882a593Smuzhiyun * obtaining a copy of this software and associated documentation files 7*4882a593Smuzhiyun * (the "Software"), to deal in the Software without restriction, 8*4882a593Smuzhiyun * including without limitation the rights to use, copy, modify, merge, 9*4882a593Smuzhiyun * publish, distribute, sublicense, and/or sell copies of the Software, 10*4882a593Smuzhiyun * and to permit persons to whom the Software is furnished to do so, 11*4882a593Smuzhiyun * subject to the following conditions: 12*4882a593Smuzhiyun * 13*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be 14*4882a593Smuzhiyun * included in all copies or substantial portions of the Software. 15*4882a593Smuzhiyun * 16*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT 20*4882a593Smuzhiyun * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21*4882a593Smuzhiyun * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22*4882a593Smuzhiyun * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE. 24*4882a593Smuzhiyun * 25*4882a593Smuzhiyun * Except as contained in this notice, the name(s) of the above 26*4882a593Smuzhiyun * copyright holders shall not be used in advertising or otherwise to 27*4882a593Smuzhiyun * promote the sale, use or other dealings in this Software without 28*4882a593Smuzhiyun * prior written authorization. 29*4882a593Smuzhiyun */ 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun#include "pbproxy.h" 32*4882a593Smuzhiyun#import "x-selection.h" 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun#include <CoreFoundation/CFSocket.h> 35*4882a593Smuzhiyun#include <CoreFoundation/CFRunLoop.h> 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun#include <X11/Xatom.h> 38*4882a593Smuzhiyun#include <X11/keysym.h> 39*4882a593Smuzhiyun#include <X11/extensions/applewm.h> 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun#include <unistd.h> 42*4882a593Smuzhiyun 43*4882a593Smuzhiyunstatic CFRunLoopSourceRef xpbproxy_dpy_source; 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun#ifdef STANDALONE_XPBPROXY 46*4882a593SmuzhiyunBOOL xpbproxy_prefs_reload = NO; 47*4882a593Smuzhiyun#endif 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun/* Timestamp when the X server last told us it's active */ 50*4882a593Smuzhiyunstatic Time last_activation_time; 51*4882a593Smuzhiyun 52*4882a593Smuzhiyunstatic void 53*4882a593Smuzhiyunx_event_apple_wm_notify(XAppleWMNotifyEvent *e) 54*4882a593Smuzhiyun{ 55*4882a593Smuzhiyun int type = e->type - xpbproxy_apple_wm_event_base; 56*4882a593Smuzhiyun int kind = e->kind; 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* We want to reload prefs even if we're not active */ 59*4882a593Smuzhiyun if (type == AppleWMActivationNotify && 60*4882a593Smuzhiyun kind == AppleWMReloadPreferences) 61*4882a593Smuzhiyun [xpbproxy_selection_object ()reload_preferences]; 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun if (![xpbproxy_selection_object ()is_active]) 64*4882a593Smuzhiyun return; 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun switch (type) { 67*4882a593Smuzhiyun case AppleWMActivationNotify: 68*4882a593Smuzhiyun switch (kind) { 69*4882a593Smuzhiyun case AppleWMIsActive: 70*4882a593Smuzhiyun last_activation_time = e->time; 71*4882a593Smuzhiyun [xpbproxy_selection_object () x_active:e->time]; 72*4882a593Smuzhiyun break; 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun case AppleWMIsInactive: 75*4882a593Smuzhiyun [xpbproxy_selection_object () x_inactive:e->time]; 76*4882a593Smuzhiyun break; 77*4882a593Smuzhiyun } 78*4882a593Smuzhiyun break; 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun case AppleWMPasteboardNotify: 81*4882a593Smuzhiyun switch (kind) { 82*4882a593Smuzhiyun case AppleWMCopyToPasteboard: 83*4882a593Smuzhiyun [xpbproxy_selection_object () x_copy:e->time]; 84*4882a593Smuzhiyun } 85*4882a593Smuzhiyun break; 86*4882a593Smuzhiyun } 87*4882a593Smuzhiyun} 88*4882a593Smuzhiyun 89*4882a593Smuzhiyunstatic void 90*4882a593Smuzhiyunxpbproxy_process_xevents(void) 91*4882a593Smuzhiyun{ 92*4882a593Smuzhiyun while (XPending(xpbproxy_dpy) != 0) { @autoreleasepool { 93*4882a593Smuzhiyun XEvent e; 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun XNextEvent(xpbproxy_dpy, &e); 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun switch (e.type) { 98*4882a593Smuzhiyun case SelectionClear: 99*4882a593Smuzhiyun if ([xpbproxy_selection_object ()is_active]) 100*4882a593Smuzhiyun [xpbproxy_selection_object () clear_event:&e.xselectionclear]; 101*4882a593Smuzhiyun break; 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun case SelectionRequest: 104*4882a593Smuzhiyun [xpbproxy_selection_object () request_event:&e.xselectionrequest]; 105*4882a593Smuzhiyun break; 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun case SelectionNotify: 108*4882a593Smuzhiyun [xpbproxy_selection_object () notify_event:&e.xselection]; 109*4882a593Smuzhiyun break; 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun case PropertyNotify: 112*4882a593Smuzhiyun [xpbproxy_selection_object () property_event:&e.xproperty]; 113*4882a593Smuzhiyun break; 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun default: 116*4882a593Smuzhiyun if (e.type >= xpbproxy_apple_wm_event_base && 117*4882a593Smuzhiyun e.type < xpbproxy_apple_wm_event_base + 118*4882a593Smuzhiyun AppleWMNumberEvents) { 119*4882a593Smuzhiyun x_event_apple_wm_notify((XAppleWMNotifyEvent *)&e); 120*4882a593Smuzhiyun } 121*4882a593Smuzhiyun else if (e.type == xpbproxy_xfixes_event_base + 122*4882a593Smuzhiyun XFixesSelectionNotify) { 123*4882a593Smuzhiyun [xpbproxy_selection_object () xfixes_selection_notify:( 124*4882a593Smuzhiyun XFixesSelectionNotifyEvent *)&e]; 125*4882a593Smuzhiyun } 126*4882a593Smuzhiyun break; 127*4882a593Smuzhiyun } 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun XFlush(xpbproxy_dpy); 130*4882a593Smuzhiyun }} 131*4882a593Smuzhiyun} 132*4882a593Smuzhiyun 133*4882a593Smuzhiyunstatic BOOL 134*4882a593Smuzhiyunadd_input_socket(int sock, CFOptionFlags callback_types, 135*4882a593Smuzhiyun CFSocketCallBack callback, const CFSocketContext *ctx, 136*4882a593Smuzhiyun CFRunLoopSourceRef *cf_source) 137*4882a593Smuzhiyun{ 138*4882a593Smuzhiyun CFSocketRef cf_sock; 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun cf_sock = CFSocketCreateWithNative(kCFAllocatorDefault, sock, 141*4882a593Smuzhiyun callback_types, callback, ctx); 142*4882a593Smuzhiyun if (cf_sock == NULL) { 143*4882a593Smuzhiyun close(sock); 144*4882a593Smuzhiyun return FALSE; 145*4882a593Smuzhiyun } 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun *cf_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, 148*4882a593Smuzhiyun cf_sock, 0); 149*4882a593Smuzhiyun CFRelease(cf_sock); 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun if (*cf_source == NULL) 152*4882a593Smuzhiyun return FALSE; 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun CFRunLoopAddSource(CFRunLoopGetCurrent(), 155*4882a593Smuzhiyun *cf_source, kCFRunLoopDefaultMode); 156*4882a593Smuzhiyun return TRUE; 157*4882a593Smuzhiyun} 158*4882a593Smuzhiyun 159*4882a593Smuzhiyunstatic void 160*4882a593Smuzhiyunx_input_callback(CFSocketRef sock, CFSocketCallBackType type, 161*4882a593Smuzhiyun CFDataRef address, const void *data, void *info) 162*4882a593Smuzhiyun{ 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun#ifdef STANDALONE_XPBPROXY 165*4882a593Smuzhiyun if (xpbproxy_prefs_reload) { 166*4882a593Smuzhiyun [xpbproxy_selection_object ()reload_preferences]; 167*4882a593Smuzhiyun xpbproxy_prefs_reload = NO; 168*4882a593Smuzhiyun } 169*4882a593Smuzhiyun#endif 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun xpbproxy_process_xevents(); 172*4882a593Smuzhiyun} 173*4882a593Smuzhiyun 174*4882a593SmuzhiyunBOOL 175*4882a593Smuzhiyunxpbproxy_input_register(void) 176*4882a593Smuzhiyun{ 177*4882a593Smuzhiyun return add_input_socket(ConnectionNumber( 178*4882a593Smuzhiyun xpbproxy_dpy), kCFSocketReadCallBack, 179*4882a593Smuzhiyun x_input_callback, NULL, &xpbproxy_dpy_source); 180*4882a593Smuzhiyun} 181