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