14642e01fSmrg/* x-input.m -- event handling 235c4bbdfSmrg * 335c4bbdfSmrg * Copyright (c) 2002-2012 Apple Inc. All rights reserved. 435c4bbdfSmrg * 535c4bbdfSmrg * Permission is hereby granted, free of charge, to any person 635c4bbdfSmrg * obtaining a copy of this software and associated documentation files 735c4bbdfSmrg * (the "Software"), to deal in the Software without restriction, 835c4bbdfSmrg * including without limitation the rights to use, copy, modify, merge, 935c4bbdfSmrg * publish, distribute, sublicense, and/or sell copies of the Software, 1035c4bbdfSmrg * and to permit persons to whom the Software is furnished to do so, 1135c4bbdfSmrg * subject to the following conditions: 1235c4bbdfSmrg * 1335c4bbdfSmrg * The above copyright notice and this permission notice shall be 1435c4bbdfSmrg * included in all copies or substantial portions of the Software. 1535c4bbdfSmrg * 1635c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1735c4bbdfSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1835c4bbdfSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1935c4bbdfSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT 2035c4bbdfSmrg * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 2135c4bbdfSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2235c4bbdfSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2335c4bbdfSmrg * DEALINGS IN THE SOFTWARE. 2435c4bbdfSmrg * 2535c4bbdfSmrg * Except as contained in this notice, the name(s) of the above 2635c4bbdfSmrg * copyright holders shall not be used in advertising or otherwise to 2735c4bbdfSmrg * promote the sale, use or other dealings in this Software without 2835c4bbdfSmrg * prior written authorization. 294642e01fSmrg */ 304642e01fSmrg 314642e01fSmrg#include "pbproxy.h" 324642e01fSmrg#import "x-selection.h" 334642e01fSmrg 344642e01fSmrg#include <CoreFoundation/CFSocket.h> 354642e01fSmrg#include <CoreFoundation/CFRunLoop.h> 364642e01fSmrg 374642e01fSmrg#include <X11/Xatom.h> 384642e01fSmrg#include <X11/keysym.h> 394642e01fSmrg#include <X11/extensions/applewm.h> 404642e01fSmrg 414642e01fSmrg#include <unistd.h> 424642e01fSmrg 434642e01fSmrgstatic CFRunLoopSourceRef xpbproxy_dpy_source; 444642e01fSmrg 454642e01fSmrg#ifdef STANDALONE_XPBPROXY 464642e01fSmrgBOOL xpbproxy_prefs_reload = NO; 474642e01fSmrg#endif 484642e01fSmrg 494642e01fSmrg/* Timestamp when the X server last told us it's active */ 504642e01fSmrgstatic Time last_activation_time; 514642e01fSmrg 5235c4bbdfSmrgstatic void 5335c4bbdfSmrgx_event_apple_wm_notify(XAppleWMNotifyEvent *e) 5435c4bbdfSmrg{ 554642e01fSmrg int type = e->type - xpbproxy_apple_wm_event_base; 564642e01fSmrg int kind = e->kind; 574642e01fSmrg 584642e01fSmrg /* We want to reload prefs even if we're not active */ 5935c4bbdfSmrg if (type == AppleWMActivationNotify && 6035c4bbdfSmrg kind == AppleWMReloadPreferences) 6135c4bbdfSmrg [xpbproxy_selection_object ()reload_preferences]; 624642e01fSmrg 6335c4bbdfSmrg if (![xpbproxy_selection_object ()is_active]) 644642e01fSmrg return; 654642e01fSmrg 6635c4bbdfSmrg switch (type) { 6735c4bbdfSmrg case AppleWMActivationNotify: 6835c4bbdfSmrg switch (kind) { 6935c4bbdfSmrg case AppleWMIsActive: 7035c4bbdfSmrg last_activation_time = e->time; 7135c4bbdfSmrg [xpbproxy_selection_object () x_active:e->time]; 724642e01fSmrg break; 7335c4bbdfSmrg 7435c4bbdfSmrg case AppleWMIsInactive: 7535c4bbdfSmrg [xpbproxy_selection_object () x_inactive:e->time]; 764642e01fSmrg break; 7735c4bbdfSmrg } 7835c4bbdfSmrg break; 7935c4bbdfSmrg 8035c4bbdfSmrg case AppleWMPasteboardNotify: 8135c4bbdfSmrg switch (kind) { 8235c4bbdfSmrg case AppleWMCopyToPasteboard: 8335c4bbdfSmrg [xpbproxy_selection_object () x_copy:e->time]; 8435c4bbdfSmrg } 8535c4bbdfSmrg break; 864642e01fSmrg } 874642e01fSmrg} 884642e01fSmrg 8935c4bbdfSmrgstatic void 9035c4bbdfSmrgxpbproxy_process_xevents(void) 9135c4bbdfSmrg{ 92c8548ba8Smrg while (XPending(xpbproxy_dpy) != 0) { @autoreleasepool { 936747b715Smrg XEvent e; 9435c4bbdfSmrg 9535c4bbdfSmrg XNextEvent(xpbproxy_dpy, &e); 9635c4bbdfSmrg 9735c4bbdfSmrg switch (e.type) { 9835c4bbdfSmrg case SelectionClear: 9935c4bbdfSmrg if ([xpbproxy_selection_object ()is_active]) 10035c4bbdfSmrg [xpbproxy_selection_object () clear_event:&e.xselectionclear]; 10135c4bbdfSmrg break; 10235c4bbdfSmrg 10335c4bbdfSmrg case SelectionRequest: 10435c4bbdfSmrg [xpbproxy_selection_object () request_event:&e.xselectionrequest]; 10535c4bbdfSmrg break; 10635c4bbdfSmrg 10735c4bbdfSmrg case SelectionNotify: 10835c4bbdfSmrg [xpbproxy_selection_object () notify_event:&e.xselection]; 10935c4bbdfSmrg break; 11035c4bbdfSmrg 11135c4bbdfSmrg case PropertyNotify: 11235c4bbdfSmrg [xpbproxy_selection_object () property_event:&e.xproperty]; 11335c4bbdfSmrg break; 11435c4bbdfSmrg 11535c4bbdfSmrg default: 11635c4bbdfSmrg if (e.type >= xpbproxy_apple_wm_event_base && 11735c4bbdfSmrg e.type < xpbproxy_apple_wm_event_base + 11835c4bbdfSmrg AppleWMNumberEvents) { 11935c4bbdfSmrg x_event_apple_wm_notify((XAppleWMNotifyEvent *)&e); 12035c4bbdfSmrg } 12135c4bbdfSmrg else if (e.type == xpbproxy_xfixes_event_base + 12235c4bbdfSmrg XFixesSelectionNotify) { 12335c4bbdfSmrg [xpbproxy_selection_object () xfixes_selection_notify:( 12435c4bbdfSmrg XFixesSelectionNotifyEvent *)&e]; 12535c4bbdfSmrg } 12635c4bbdfSmrg break; 1274642e01fSmrg } 12835c4bbdfSmrg 1296747b715Smrg XFlush(xpbproxy_dpy); 130c8548ba8Smrg }} 1314642e01fSmrg} 1324642e01fSmrg 13335c4bbdfSmrgstatic BOOL 13435c4bbdfSmrgadd_input_socket(int sock, CFOptionFlags callback_types, 13535c4bbdfSmrg CFSocketCallBack callback, const CFSocketContext *ctx, 13635c4bbdfSmrg CFRunLoopSourceRef *cf_source) 13735c4bbdfSmrg{ 1384642e01fSmrg CFSocketRef cf_sock; 13935c4bbdfSmrg 14035c4bbdfSmrg cf_sock = CFSocketCreateWithNative(kCFAllocatorDefault, sock, 14135c4bbdfSmrg callback_types, callback, ctx); 1424642e01fSmrg if (cf_sock == NULL) { 14335c4bbdfSmrg close(sock); 1444642e01fSmrg return FALSE; 1454642e01fSmrg } 14635c4bbdfSmrg 14735c4bbdfSmrg *cf_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, 14835c4bbdfSmrg cf_sock, 0); 14935c4bbdfSmrg CFRelease(cf_sock); 15035c4bbdfSmrg 1514642e01fSmrg if (*cf_source == NULL) 1524642e01fSmrg return FALSE; 15335c4bbdfSmrg 15435c4bbdfSmrg CFRunLoopAddSource(CFRunLoopGetCurrent(), 15535c4bbdfSmrg *cf_source, kCFRunLoopDefaultMode); 1564642e01fSmrg return TRUE; 1574642e01fSmrg} 1584642e01fSmrg 15935c4bbdfSmrgstatic void 16035c4bbdfSmrgx_input_callback(CFSocketRef sock, CFSocketCallBackType type, 16135c4bbdfSmrg CFDataRef address, const void *data, void *info) 16235c4bbdfSmrg{ 1634642e01fSmrg 1644642e01fSmrg#ifdef STANDALONE_XPBPROXY 16535c4bbdfSmrg if (xpbproxy_prefs_reload) { 16635c4bbdfSmrg [xpbproxy_selection_object ()reload_preferences]; 1674642e01fSmrg xpbproxy_prefs_reload = NO; 1684642e01fSmrg } 1694642e01fSmrg#endif 17035c4bbdfSmrg 1716747b715Smrg xpbproxy_process_xevents(); 1724642e01fSmrg} 1734642e01fSmrg 17435c4bbdfSmrgBOOL 17535c4bbdfSmrgxpbproxy_input_register(void) 17635c4bbdfSmrg{ 17735c4bbdfSmrg return add_input_socket(ConnectionNumber( 17835c4bbdfSmrg xpbproxy_dpy), kCFSocketReadCallBack, 1794642e01fSmrg x_input_callback, NULL, &xpbproxy_dpy_source); 1804642e01fSmrg} 181