main.m revision 4642e01f
1/* main.m
2   Copyright (c) 2002, 2008 Apple Computer, Inc. All rights reserved.
3
4   Permission is hereby granted, free of charge, to any person
5   obtaining a copy of this software and associated documentation files
6   (the "Software"), to deal in the Software without restriction,
7   including without limitation the rights to use, copy, modify, merge,
8   publish, distribute, sublicense, and/or sell copies of the Software,
9   and to permit persons to whom the Software is furnished to do so,
10   subject to the following conditions:
11
12   The above copyright notice and this permission notice shall be
13   included in all copies or substantial portions of the Software.
14
15   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18   NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
19   HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22   DEALINGS IN THE SOFTWARE.
23
24   Except as contained in this notice, the name(s) of the above
25   copyright holders shall not be used in advertising or otherwise to
26   promote the sale, use or other dealings in this Software without
27   prior written authorization.
28 */
29
30#include "pbproxy.h"
31#import "x-selection.h"
32
33#include <pthread.h>
34#include <unistd.h>
35#include <X11/extensions/applewm.h>
36
37Display *xpbproxy_dpy;
38int xpbproxy_apple_wm_event_base, xpbproxy_apple_wm_error_base;
39int xpbproxy_xfixes_event_base, xpbproxy_xfixes_error_base;
40BOOL xpbproxy_have_xfixes;
41
42extern char *display;
43
44#ifdef STANDALONE_XPBPROXY
45BOOL xpbproxy_is_standalone = NO;
46#endif
47
48x_selection *_selection_object;
49
50static int x_io_error_handler (Display *dpy) {
51    /* We lost our connection to the server. */
52    
53    TRACE ();
54
55    /* trigger the thread to restart?
56     *   NO - this would be to a "deeper" problem, and restarts would just
57     *        make things worse...
58     */
59#ifdef STANDALONE_XPBPROXY
60    if(xpbproxy_is_standalone)
61        exit(EXIT_FAILURE);
62#endif
63
64    return 0;
65}
66
67static int x_error_handler (Display *dpy, XErrorEvent *errevent) {
68    return 0;
69}
70
71static inline pthread_t create_thread(void *func, void *arg) {
72    pthread_attr_t attr;
73    pthread_t tid;
74    
75    pthread_attr_init(&attr);
76    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
77    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
78    pthread_create(&tid, &attr, func, arg);
79    pthread_attr_destroy(&attr);
80    
81    return tid;
82}
83
84static void *xpbproxy_x_thread(void *args) {
85    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
86    size_t i;
87
88    for(i=0, xpbproxy_dpy=NULL; !xpbproxy_dpy && i<5; i++) {
89        xpbproxy_dpy = XOpenDisplay(NULL);
90        
91        if(!xpbproxy_dpy && display) {
92            char _display[32];
93            snprintf(_display, sizeof(_display), ":%s", display);
94            setenv("DISPLAY", _display, TRUE);
95
96            xpbproxy_dpy=XOpenDisplay(_display);
97        }
98        if(!xpbproxy_dpy)
99            sleep(1);
100    }
101    
102    if (xpbproxy_dpy == NULL) {
103        fprintf (stderr, "xpbproxy: can't open default display\n");
104        [pool release];
105        return NULL;
106    }
107    
108    XSetIOErrorHandler (x_io_error_handler);
109    XSetErrorHandler (x_error_handler);
110    
111    if (!XAppleWMQueryExtension (xpbproxy_dpy, &xpbproxy_apple_wm_event_base,
112                                 &xpbproxy_apple_wm_error_base)) {
113        fprintf (stderr, "xpbproxy: can't open AppleWM server extension\n");
114        [pool release];
115        return NULL;
116    }
117    
118    xpbproxy_have_xfixes = XFixesQueryExtension(xpbproxy_dpy, &xpbproxy_xfixes_event_base, &xpbproxy_xfixes_error_base);
119    
120    XAppleWMSelectInput (xpbproxy_dpy, AppleWMActivationNotifyMask |
121                         AppleWMPasteboardNotifyMask);
122    
123    _selection_object = [[x_selection alloc] init];
124    
125    if(!xpbproxy_input_register()) {
126        [pool release];
127        return NULL;
128    }
129
130    [pool release];
131 
132    xpbproxy_input_loop();
133    return NULL;
134}
135
136BOOL xpbproxy_init (void) {
137    create_thread(xpbproxy_x_thread, NULL);
138    return TRUE;
139}
140
141id xpbproxy_selection_object (void) {
142    return _selection_object;
143}
144
145Time xpbproxy_current_timestamp (void) {
146    /* FIXME: may want to fetch a timestamp from the server.. */
147    return CurrentTime;
148}
149
150void debug_printf (const char *fmt, ...) {
151    static int spew = -1;
152    
153    if (spew == -1) {
154        char *x = getenv ("DEBUG");
155        spew = (x != NULL && atoi (x) != 0);
156    }
157    
158    if (spew) {
159        va_list args;
160        va_start(args, fmt);
161        vfprintf (stderr, fmt, args);
162        va_end(args);
163    }
164}
165