1706f2543Smrg/* main.m
2706f2543Smrg   Copyright (c) 2002, 2008 Apple Computer, Inc. All rights reserved.
3706f2543Smrg
4706f2543Smrg   Permission is hereby granted, free of charge, to any person
5706f2543Smrg   obtaining a copy of this software and associated documentation files
6706f2543Smrg   (the "Software"), to deal in the Software without restriction,
7706f2543Smrg   including without limitation the rights to use, copy, modify, merge,
8706f2543Smrg   publish, distribute, sublicense, and/or sell copies of the Software,
9706f2543Smrg   and to permit persons to whom the Software is furnished to do so,
10706f2543Smrg   subject to the following conditions:
11706f2543Smrg
12706f2543Smrg   The above copyright notice and this permission notice shall be
13706f2543Smrg   included in all copies or substantial portions of the Software.
14706f2543Smrg
15706f2543Smrg   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16706f2543Smrg   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17706f2543Smrg   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18706f2543Smrg   NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
19706f2543Smrg   HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20706f2543Smrg   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21706f2543Smrg   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22706f2543Smrg   DEALINGS IN THE SOFTWARE.
23706f2543Smrg
24706f2543Smrg   Except as contained in this notice, the name(s) of the above
25706f2543Smrg   copyright holders shall not be used in advertising or otherwise to
26706f2543Smrg   promote the sale, use or other dealings in this Software without
27706f2543Smrg   prior written authorization.
28706f2543Smrg */
29706f2543Smrg
30706f2543Smrg#include "pbproxy.h"
31706f2543Smrg#import "x-selection.h"
32706f2543Smrg
33706f2543Smrg#include <pthread.h>
34706f2543Smrg#include <unistd.h>
35706f2543Smrg#include <X11/extensions/applewm.h>
36706f2543Smrg
37706f2543SmrgDisplay *xpbproxy_dpy;
38706f2543Smrgint xpbproxy_apple_wm_event_base, xpbproxy_apple_wm_error_base;
39706f2543Smrgint xpbproxy_xfixes_event_base, xpbproxy_xfixes_error_base;
40706f2543SmrgBOOL xpbproxy_have_xfixes;
41706f2543Smrg
42706f2543Smrgextern char *display;
43706f2543Smrg
44706f2543Smrg#ifdef STANDALONE_XPBPROXY
45706f2543SmrgBOOL xpbproxy_is_standalone = NO;
46706f2543Smrg#endif
47706f2543Smrg
48706f2543Smrgx_selection *_selection_object;
49706f2543Smrg
50706f2543Smrgextern BOOL serverRunning;
51706f2543Smrgextern pthread_mutex_t serverRunningMutex;
52706f2543Smrgextern pthread_cond_t serverRunningCond;
53706f2543Smrg
54706f2543Smrgstatic inline void wait_for_server_init(void) {
55706f2543Smrg    /* If the server hasn't finished initializing, wait for it... */
56706f2543Smrg    if(!serverRunning) {
57706f2543Smrg        pthread_mutex_lock(&serverRunningMutex);
58706f2543Smrg        while(!serverRunning)
59706f2543Smrg            pthread_cond_wait(&serverRunningCond, &serverRunningMutex);
60706f2543Smrg        pthread_mutex_unlock(&serverRunningMutex);
61706f2543Smrg    }
62706f2543Smrg}
63706f2543Smrg
64706f2543Smrgstatic int x_io_error_handler (Display *dpy) {
65706f2543Smrg    /* We lost our connection to the server. */
66706f2543Smrg    
67706f2543Smrg    TRACE ();
68706f2543Smrg
69706f2543Smrg    /* trigger the thread to restart?
70706f2543Smrg     *   NO - this would be to a "deeper" problem, and restarts would just
71706f2543Smrg     *        make things worse...
72706f2543Smrg     */
73706f2543Smrg#ifdef STANDALONE_XPBPROXY
74706f2543Smrg    if(xpbproxy_is_standalone)
75706f2543Smrg        exit(EXIT_FAILURE);
76706f2543Smrg#endif
77706f2543Smrg
78706f2543Smrg    /* Prevent _XIOError from calling exit() */
79706f2543Smrg    pthread_exit(NULL);
80706f2543Smrg    return 0;
81706f2543Smrg}
82706f2543Smrg
83706f2543Smrgstatic int x_error_handler (Display *dpy, XErrorEvent *errevent) {
84706f2543Smrg    return 0;
85706f2543Smrg}
86706f2543Smrg
87706f2543Smrgint xpbproxy_run (void) {
88706f2543Smrg    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
89706f2543Smrg    size_t i;
90706f2543Smrg    
91706f2543Smrg    wait_for_server_init();
92706f2543Smrg    
93706f2543Smrg    for(i=0, xpbproxy_dpy=NULL; !xpbproxy_dpy && i<5; i++) {
94706f2543Smrg        xpbproxy_dpy = XOpenDisplay(NULL);
95706f2543Smrg        
96706f2543Smrg        if(!xpbproxy_dpy && display) {
97706f2543Smrg            char _display[32];
98706f2543Smrg            snprintf(_display, sizeof(_display), ":%s", display);
99706f2543Smrg            setenv("DISPLAY", _display, TRUE);
100706f2543Smrg            
101706f2543Smrg            xpbproxy_dpy=XOpenDisplay(_display);
102706f2543Smrg        }
103706f2543Smrg        if(!xpbproxy_dpy)
104706f2543Smrg            sleep(1);
105706f2543Smrg    }
106706f2543Smrg    
107706f2543Smrg    if (xpbproxy_dpy == NULL) {
108706f2543Smrg        fprintf (stderr, "xpbproxy: can't open default display\n");
109706f2543Smrg        [pool release];
110706f2543Smrg        return EXIT_FAILURE;
111706f2543Smrg    }
112706f2543Smrg    
113706f2543Smrg    XSetIOErrorHandler (x_io_error_handler);
114706f2543Smrg    XSetErrorHandler (x_error_handler);
115706f2543Smrg    
116706f2543Smrg    if (!XAppleWMQueryExtension (xpbproxy_dpy, &xpbproxy_apple_wm_event_base,
117706f2543Smrg                                 &xpbproxy_apple_wm_error_base)) {
118706f2543Smrg        fprintf (stderr, "xpbproxy: can't open AppleWM server extension\n");
119706f2543Smrg        [pool release];
120706f2543Smrg        return EXIT_FAILURE;
121706f2543Smrg    }
122706f2543Smrg
123706f2543Smrg    xpbproxy_have_xfixes = XFixesQueryExtension(xpbproxy_dpy, &xpbproxy_xfixes_event_base, &xpbproxy_xfixes_error_base);
124706f2543Smrg
125706f2543Smrg    XAppleWMSelectInput (xpbproxy_dpy, AppleWMActivationNotifyMask |
126706f2543Smrg                         AppleWMPasteboardNotifyMask);
127706f2543Smrg    
128706f2543Smrg    _selection_object = [[x_selection alloc] init];
129706f2543Smrg    
130706f2543Smrg    if(!xpbproxy_input_register()) {
131706f2543Smrg        [pool release];
132706f2543Smrg        return EXIT_FAILURE;
133706f2543Smrg    }
134706f2543Smrg    
135706f2543Smrg    [pool release];
136706f2543Smrg    
137706f2543Smrg    CFRunLoopRun();
138706f2543Smrg
139706f2543Smrg    return EXIT_SUCCESS;
140706f2543Smrg}
141706f2543Smrg
142706f2543Smrgid xpbproxy_selection_object (void) {
143706f2543Smrg    return _selection_object;
144706f2543Smrg}
145706f2543Smrg
146706f2543SmrgTime xpbproxy_current_timestamp (void) {
147706f2543Smrg    /* FIXME: may want to fetch a timestamp from the server.. */
148706f2543Smrg    return CurrentTime;
149706f2543Smrg}
150706f2543Smrg
151706f2543Smrgvoid debug_printf (const char *fmt, ...) {
152706f2543Smrg    static int spew = -1;
153706f2543Smrg    
154706f2543Smrg    if (spew == -1) {
155706f2543Smrg        char *x = getenv ("DEBUG");
156706f2543Smrg        spew = (x != NULL && atoi (x) != 0);
157706f2543Smrg    }
158706f2543Smrg    
159706f2543Smrg    if (spew) {
160706f2543Smrg        va_list args;
161706f2543Smrg        va_start(args, fmt);
162706f2543Smrg        vfprintf (stderr, fmt, args);
163706f2543Smrg        va_end(args);
164706f2543Smrg    }
165706f2543Smrg}
166