summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Huddleston <jeremyhu@freedesktop.org>2008-10-04 18:54:15 -0700
committerJeremy Huddleston <jeremyhu@freedesktop.org>2008-10-04 21:17:02 -0700
commitb3a971d8b5df5ab4af0be49105ef32f67d010901 (patch)
tree470bd2cdf7aa59db5156cae7845fc97dfe4d237e
parentfc35c7a2e2888cb767413f5e85a79c7f422a6284 (diff)
XQuartz: xpbproxy: Support some of the preference toggles from X11.app, cleaned up CLIPBOARD_MANAGER atom management.
(cherry picked from commit f7673bb4de3c1f71eb390a3279eed3589efc3df4)
-rw-r--r--hw/xquartz/pbproxy/app-main.m4
-rw-r--r--hw/xquartz/pbproxy/main.m4
-rw-r--r--hw/xquartz/pbproxy/pbproxy.h4
-rw-r--r--hw/xquartz/pbproxy/x-input.m60
-rw-r--r--hw/xquartz/pbproxy/x-selection.h2
-rw-r--r--hw/xquartz/pbproxy/x-selection.m185
6 files changed, 144 insertions, 115 deletions
diff --git a/hw/xquartz/pbproxy/app-main.m b/hw/xquartz/pbproxy/app-main.m
index 7611eefea..4847851fa 100644
--- a/hw/xquartz/pbproxy/app-main.m
+++ b/hw/xquartz/pbproxy/app-main.m
@@ -15,8 +15,10 @@ static void signal_handler (int sig) {
}
int main (int argc, const char *argv[]) {
+#ifdef TEST
printf("pid: %u\n", getpid());
-
+#endif
+
x_init ();
signal (SIGINT, signal_handler);
diff --git a/hw/xquartz/pbproxy/main.m b/hw/xquartz/pbproxy/main.m
index e2156a758..448bec4e0 100644
--- a/hw/xquartz/pbproxy/main.m
+++ b/hw/xquartz/pbproxy/main.m
@@ -55,10 +55,6 @@ void x_init (void) {
_selection_object = [[x_selection alloc] init];
x_input_register ();
-
- [_selection_object set_clipboard_manager];
- [_selection_object claim_clipboard];
-
x_input_run ();
[pool release];
diff --git a/hw/xquartz/pbproxy/pbproxy.h b/hw/xquartz/pbproxy/pbproxy.h
index bd5f65b4f..bfeb8685a 100644
--- a/hw/xquartz/pbproxy/pbproxy.h
+++ b/hw/xquartz/pbproxy/pbproxy.h
@@ -12,7 +12,9 @@
#include <X11/extensions/shape.h>
#undef Cursor
+#ifndef DEBUG
#define DEBUG 0
+#endif
/* from main.m */
extern void x_set_is_active (BOOL state);
@@ -27,7 +29,7 @@ extern int x_apple_wm_event_base, x_apple_wm_error_base;
/* from x-input.m */
extern void x_input_register (void);
extern void x_input_run (void);
-
+
#if DEBUG == 0
# define DB(msg, args...) do {} while (0)
#else
diff --git a/hw/xquartz/pbproxy/x-input.m b/hw/xquartz/pbproxy/x-input.m
index c11ffb382..1b2475cb9 100644
--- a/hw/xquartz/pbproxy/x-input.m
+++ b/hw/xquartz/pbproxy/x-input.m
@@ -21,29 +21,35 @@ static CFRunLoopSourceRef x_dpy_source;
static Time last_activation_time;
static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) {
+ int type = e->type - x_apple_wm_event_base;
+ int kind = e->kind;
- switch (e->type - x_apple_wm_event_base) {
+ /* We want to reload prefs even if we're not active */
+ if(type == AppleWMActivationNotify &&
+ kind == AppleWMReloadPreferences)
+ [x_selection_object() reload_preferences];
+
+ if(![x_selection_object() is_active])
+ return;
+
+ switch (type) {
case AppleWMActivationNotify:
- switch (e->kind) {
+ switch (kind) {
case AppleWMIsActive:
last_activation_time = e->time;
- [x_selection_object () x_active:e->time];
+ [x_selection_object() x_active:e->time];
break;
case AppleWMIsInactive:
- [x_selection_object () x_inactive:e->time];
+ [x_selection_object() x_inactive:e->time];
break;
-
- case AppleWMReloadPreferences:
- [x_selection_object () reload_preferences];
- break;
}
break;
case AppleWMPasteboardNotify:
- switch (e->kind) {
- case AppleWMCopyToPasteboard:
- [x_selection_object () x_copy:e->time];
+ switch (kind) {
+ case AppleWMCopyToPasteboard:
+ [x_selection_object() x_copy:e->time];
}
break;
}
@@ -54,22 +60,18 @@ void x_input_run (void) {
if (nil == pool)
{
- fprintf(stderr, "unable to allocate/init auto release pool!\n");
- return;
+ fprintf(stderr, "unable to allocate/init auto release pool!\n");
+ return;
}
-
+
while (XPending (x_dpy) != 0) {
- XEvent e;
-
+ XEvent e;
XNextEvent (x_dpy, &e);
-
- /* If pbproxy isn't active (in the preferences), then don't do anything. */
- if (![x_selection_object() is_active])
- continue;
-
+
switch (e.type) {
case SelectionClear:
- [x_selection_object () clear_event:&e.xselectionclear];
+ if([x_selection_object() is_active])
+ [x_selection_object () clear_event:&e.xselectionclear];
break;
case SelectionRequest:
@@ -80,10 +82,10 @@ void x_input_run (void) {
[x_selection_object () notify_event:&e.xselection];
break;
- case PropertyNotify:
- [x_selection_object () property_event:&e.xproperty];
- break;
-
+ case PropertyNotify:
+ [x_selection_object () property_event:&e.xproperty];
+ break;
+
default:
if (e.type - x_apple_wm_event_base >= 0
&& e.type - x_apple_wm_event_base < AppleWMNumberEvents) {
@@ -91,10 +93,10 @@ void x_input_run (void) {
}
break;
}
-
- XFlush(x_dpy);
+
+ XFlush(x_dpy);
}
-
+
[pool release];
}
diff --git a/hw/xquartz/pbproxy/x-selection.h b/hw/xquartz/pbproxy/x-selection.h
index 9c408b4ec..c93b6761b 100644
--- a/hw/xquartz/pbproxy/x-selection.h
+++ b/hw/xquartz/pbproxy/x-selection.h
@@ -97,7 +97,7 @@ struct atom_list {
- (void) property_event:(XPropertyEvent *)e;
- (void) handle_selection:(Atom)selection type:(Atom)type propdata:(struct propdata *)pdata;
- (void) claim_clipboard;
-- (void) set_clipboard_manager;
+- (BOOL) set_clipboard_manager_status:(BOOL)value;
- (void) own_clipboard;
- (void) copy_completed:(Atom)selection;
diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m
index 0997b3a22..67de866fe 100644
--- a/hw/xquartz/pbproxy/x-selection.m
+++ b/hw/xquartz/pbproxy/x-selection.m
@@ -56,22 +56,36 @@
/*
* TODO:
- * 1. finish handling these pbproxy control knobs.
+ * 1. handle primary_on_grab
* 2. handle MULTIPLE - I need to study the ICCCM further.
* 3. Handle PICT images properly.
+ * 4. Handle NSPasteboard updates immediately, not on active/inactive
+ * - Open xterm, run 'cat readme.txt | pbcopy'
+ * 5. Detect if CLIPBOARD_MANAGER atom belongs to a dead client rather than just None
*/
-// These will be set by X11Controller.m once this is integrated into a server thread
-BOOL pbproxy_active = YES;
-BOOL pbproxy_primary_on_grab = NO; // This is provided as an option for people who want it and has issues that won't ever be addressed to make it *always* work
-BOOL pbproxy_clipboard_to_pasteboard = YES;
-BOOL pbproxy_pasteboard_to_primary = YES;
-BOOL pbproxy_pasteboard_to_clipboard = YES;
+static struct {
+ BOOL active ;
+ BOOL primary_on_grab; // This is provided as an option for people who want it and has issues that won't ever be addressed to make it *always* work
+ BOOL clipboard_to_pasteboard;
+ BOOL pasteboard_to_primary;
+ BOOL pasteboard_to_clipboard;
+} pbproxy_prefs = { YES, NO, YES, YES, YES };
@implementation x_selection
static struct propdata null_propdata = {NULL, 0};
+#define APP_PREFS "org.x.X11"
+static BOOL prefs_get_bool (CFStringRef key, BOOL def) {
+ int ret;
+ Boolean ok;
+
+ ret = CFPreferencesGetAppBooleanValue (key, CFSTR (APP_PREFS), &ok);
+
+ return ok ? (BOOL) ret : def;
+}
+
static void
init_propdata (struct propdata *pdata)
{
@@ -321,19 +335,17 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
if (countNow != changeCount)
{
- DB ("changed pasteboard!\n");
- changeCount = countNow;
-
- if (pbproxy_pasteboard_to_primary)
- {
-
- XSetSelectionOwner (x_dpy, atoms->primary, _selection_window, CurrentTime);
- }
-
- if (pbproxy_pasteboard_to_clipboard)
- {
- [self own_clipboard];
- }
+ DB ("changed pasteboard!\n");
+ changeCount = countNow;
+
+ if (pbproxy_prefs.pasteboard_to_primary)
+ {
+ XSetSelectionOwner (x_dpy, atoms->primary, _selection_window, CurrentTime);
+ }
+
+ if (pbproxy_prefs.pasteboard_to_clipboard) {
+ [self own_clipboard];
+ }
}
#if 0
@@ -395,23 +407,36 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
}
}
-/*
- * Set pbproxy as owner of the SELECTION_MANAGER selection.
+/* Set pbproxy as owner of the SELECTION_MANAGER selection.
* This prevents tools like xclipboard from causing havoc.
+ * Returns TRUE on success
*/
-- (void) set_clipboard_manager
+- (BOOL) set_clipboard_manager_status:(BOOL)value
{
TRACE ();
- if (None != XGetSelectionOwner (x_dpy, atoms->clipboard_manager))
- {
- fprintf (stderr, "A clipboard manager is already running!\n"
- "pbproxy can not continue!\n");
- exit (EXIT_FAILURE);
+ Window owner = XGetSelectionOwner (x_dpy, atoms->clipboard_manager);
+
+ if(value) {
+ if(owner == _selection_window)
+ return TRUE;
+
+// if(None != _selection_window) {
+// fprintf (stderr, "A clipboard manager is already running. pbproxy will not sync clipboard to pasteboard.\n");
+// return FALSE;
+// }
+
+ XSetSelectionOwner(x_dpy, atoms->clipboard_manager, _selection_window, CurrentTime);
+ return (_selection_window == XGetSelectionOwner(x_dpy, atoms->clipboard_manager));
+ } else {
+ if(owner != _selection_window)
+ return TRUE;
+
+ XSetSelectionOwner(x_dpy, atoms->clipboard_manager, None, CurrentTime);
+ return(None == XGetSelectionOwner(x_dpy, atoms->clipboard_manager));
}
-
- XSetSelectionOwner (x_dpy, atoms->clipboard_manager, _selection_window,
- CurrentTime);
+
+ return FALSE;
}
/*
@@ -423,28 +448,25 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
TRACE ();
DB ("e->selection %s\n", XGetAtomName (x_dpy, e->selection));
-
- if (atoms->clipboard == e->selection)
- {
- /*
- * We lost ownership of the CLIPBOARD.
- */
- ++pending_clipboard;
-
- if (1 == pending_clipboard)
- {
- /* Claim the clipboard contents from the new owner. */
- [self claim_clipboard];
- }
- }
- else if (atoms->clipboard_manager == e->selection)
- {
- /* Another CLIPBOARD_MANAGER has set itself as owner.
- * a) we can call [self set_clipboard_manager] here and risk a war.
- * b) we can print a message and exit. Ideally we would popup a message box.
- */
- fprintf (stderr, "error: another clipboard manager was started!\n");
- //exit (EXIT_FAILURE);
+
+ if(e->selection == atoms->clipboard) {
+ /*
+ * We lost ownership of the CLIPBOARD.
+ */
+ ++pending_clipboard;
+
+ if (1 == pending_clipboard) {
+ /* Claim the clipboard contents from the new owner. */
+ [self claim_clipboard];
+ }
+ } else if(e->selection == atoms->clipboard_manager) {
+ if(pbproxy_prefs.clipboard_to_pasteboard) {
+ /* Another CLIPBOARD_MANAGER has set itself as owner. Disable syncing
+ * to avoid a race.
+ */
+ fprintf(stderr, "Another clipboard manager was started! xpbproxy is disabling syncing with clipboard.\n");
+ pbproxy_prefs.clipboard_to_pasteboard = NO;
+ }
}
}
@@ -456,32 +478,29 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
Window owner;
TRACE ();
-
- if (!pbproxy_clipboard_to_pasteboard)
- return;
+
+ if (!pbproxy_prefs.clipboard_to_pasteboard)
+ return;
owner = XGetSelectionOwner (x_dpy, atoms->clipboard);
- if (None == owner)
- {
- /*
- * The owner probably died or we are just starting up pbproxy.
- * Set pbproxy's _selection_window as the owner, and continue.
- */
- DB ("No clipboard owner.\n");
- [self copy_completed:atoms->clipboard];
- return;
- }
- else if (owner == _selection_window)
- {
- [self copy_completed:atoms->clipboard];
- return;
+ if (None == owner) {
+ /*
+ * The owner probably died or we are just starting up pbproxy.
+ * Set pbproxy's _selection_window as the owner, and continue.
+ */
+ DB ("No clipboard owner.\n");
+ [self copy_completed:atoms->clipboard];
+ return;
+ } else if (owner == _selection_window) {
+ [self copy_completed:atoms->clipboard];
+ return;
}
DB ("requesting targets\n");
-
+
request_atom = atoms->targets;
XConvertSelection (x_dpy, atoms->clipboard, atoms->targets,
- atoms->clipboard, _selection_window, CurrentTime);
+ atoms->clipboard, _selection_window, CurrentTime);
XFlush (x_dpy);
/* Now we will get a SelectionNotify event in the future. */
}
@@ -1236,18 +1255,25 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
- (void) reload_preferences
{
- if (pbproxy_clipboard_to_pasteboard)
- {
- [self claim_clipboard];
- }
+ pbproxy_prefs.active = prefs_get_bool(CFSTR("sync_pasteboard"), pbproxy_prefs.active);
+ pbproxy_prefs.primary_on_grab = prefs_get_bool(CFSTR("sync_primary_on_select"), pbproxy_prefs.primary_on_grab);
+ pbproxy_prefs.clipboard_to_pasteboard = prefs_get_bool(CFSTR("sync_clibpoard_to_pasteboard"), pbproxy_prefs.clipboard_to_pasteboard);
+ pbproxy_prefs.pasteboard_to_primary = prefs_get_bool(CFSTR("sync_pasteboard_to_primary"), pbproxy_prefs.pasteboard_to_primary);
+ pbproxy_prefs.pasteboard_to_clipboard = prefs_get_bool(CFSTR("sync_pasteboard_to_clipboard"), pbproxy_prefs.pasteboard_to_clipboard);
+
+ /* Claim or release the CLIPBOARD_MANAGER atom */
+ if(![self set_clipboard_manager_status:(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)])
+ pbproxy_prefs.clipboard_to_pasteboard = NO;
+
+ if(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)
+ [self claim_clipboard];
}
- (BOOL) is_active
{
- return pbproxy_active;
+ return pbproxy_prefs.active;
}
-
/* NSPasteboard-required methods */
- (void) paste:(id)sender
@@ -1267,7 +1293,6 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
/* Right now we don't care with this. */
}
-
/* Allocation */
- init
@@ -1310,6 +1335,8 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
pending_copy = 0;
pending_clipboard = 0;
+ [self reload_preferences];
+
return self;
}