XQuartz: implemented primary-on-grab and fixed clipboard-to-pasteboard
This commit is contained in:
parent
99be3d68b6
commit
bcb83eea72
|
@ -1,5 +1,5 @@
|
||||||
AM_CPPFLAGS=-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
|
AM_CPPFLAGS=-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
|
||||||
AM_LDFLAGS=-L/usr/X11/lib -lX11 -lAppleWM -framework AppKit -framework Foundation -framework ApplicationServices
|
AM_LDFLAGS=-L/usr/X11/lib -lX11 -lXfixes -lAppleWM -framework AppKit -framework Foundation -framework ApplicationServices
|
||||||
|
|
||||||
SOURCE_FILES = \
|
SOURCE_FILES = \
|
||||||
trick_autotools.c \
|
trick_autotools.c \
|
||||||
|
|
|
@ -19,7 +19,8 @@ int main (int argc, const char *argv[]) {
|
||||||
printf("pid: %u\n", getpid());
|
printf("pid: %u\n", getpid());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
x_init ();
|
if(x_init () !=0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
signal (SIGINT, signal_handler);
|
signal (SIGINT, signal_handler);
|
||||||
signal (SIGTERM, signal_handler);
|
signal (SIGTERM, signal_handler);
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <X11/extensions/applewm.h>
|
#include <X11/extensions/applewm.h>
|
||||||
|
#include <X11/extensions/xfixes.h>
|
||||||
|
|
||||||
Display *x_dpy;
|
Display *x_dpy;
|
||||||
int x_apple_wm_event_base, x_apple_wm_error_base;
|
int x_apple_wm_event_base, x_apple_wm_error_base;
|
||||||
|
int x_xfixes_event_base, x_xfixes_error_base;
|
||||||
|
BOOL have_xfixes;
|
||||||
|
|
||||||
x_selection *_selection_object;
|
x_selection *_selection_object;
|
||||||
|
|
||||||
|
@ -31,13 +34,13 @@ static int x_error_handler (Display *dpy, XErrorEvent *errevent) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void x_init (void) {
|
int x_init (void) {
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
x_dpy = XOpenDisplay (NULL);
|
x_dpy = XOpenDisplay (NULL);
|
||||||
if (x_dpy == NULL) {
|
if (x_dpy == NULL) {
|
||||||
fprintf (stderr, "can't open default display\n");
|
fprintf (stderr, "can't open default display\n");
|
||||||
exit (1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
XSetIOErrorHandler (x_io_error_handler);
|
XSetIOErrorHandler (x_io_error_handler);
|
||||||
|
@ -46,9 +49,11 @@ void x_init (void) {
|
||||||
if (!XAppleWMQueryExtension (x_dpy, &x_apple_wm_event_base,
|
if (!XAppleWMQueryExtension (x_dpy, &x_apple_wm_event_base,
|
||||||
&x_apple_wm_error_base)) {
|
&x_apple_wm_error_base)) {
|
||||||
fprintf (stderr, "can't open AppleWM server extension\n");
|
fprintf (stderr, "can't open AppleWM server extension\n");
|
||||||
exit (1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
have_xfixes = XFixesQueryExtension(x_dpy, &x_xfixes_event_base, &x_xfixes_error_base);
|
||||||
|
|
||||||
XAppleWMSelectInput (x_dpy, AppleWMActivationNotifyMask |
|
XAppleWMSelectInput (x_dpy, AppleWMActivationNotifyMask |
|
||||||
AppleWMPasteboardNotifyMask);
|
AppleWMPasteboardNotifyMask);
|
||||||
|
|
||||||
|
@ -58,6 +63,8 @@ void x_init (void) {
|
||||||
x_input_run ();
|
x_input_run ();
|
||||||
|
|
||||||
[pool release];
|
[pool release];
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
id x_selection_object (void) {
|
id x_selection_object (void) {
|
||||||
|
|
|
@ -21,10 +21,12 @@ extern void x_set_is_active (BOOL state);
|
||||||
extern BOOL x_get_is_active (void);
|
extern BOOL x_get_is_active (void);
|
||||||
extern id x_selection_object (void);
|
extern id x_selection_object (void);
|
||||||
extern Time x_current_timestamp (void);
|
extern Time x_current_timestamp (void);
|
||||||
extern void x_init (void);
|
extern int x_init (void);
|
||||||
|
|
||||||
extern Display *x_dpy;
|
extern Display *x_dpy;
|
||||||
extern int x_apple_wm_event_base, x_apple_wm_error_base;
|
extern int x_apple_wm_event_base, x_apple_wm_error_base;
|
||||||
|
extern int x_xfixes_event_base, x_xfixes_error_base;
|
||||||
|
extern BOOL have_xfixes;
|
||||||
|
|
||||||
/* from x-input.m */
|
/* from x-input.m */
|
||||||
extern void x_input_register (void);
|
extern void x_input_register (void);
|
||||||
|
|
|
@ -87,9 +87,11 @@ void x_input_run (void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (e.type - x_apple_wm_event_base >= 0
|
if(e.type >= x_apple_wm_event_base &&
|
||||||
&& e.type - x_apple_wm_event_base < AppleWMNumberEvents) {
|
e.type < x_apple_wm_event_base + AppleWMNumberEvents) {
|
||||||
x_event_apple_wm_notify ((XAppleWMNotifyEvent *) &e);
|
x_event_apple_wm_notify((XAppleWMNotifyEvent *) &e);
|
||||||
|
} else if(e.type == x_xfixes_event_base + XFixesSelectionNotify) {
|
||||||
|
[x_selection_object() xfixes_selection_notify:(XFixesSelectionNotifyEvent *)&e];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "pbproxy.h"
|
#include "pbproxy.h"
|
||||||
#include <AppKit/NSPasteboard.h>
|
#include <AppKit/NSPasteboard.h>
|
||||||
|
#include <X11/extensions/xfixes.h>
|
||||||
|
|
||||||
/* This stores image data or text. */
|
/* This stores image data or text. */
|
||||||
struct propdata {
|
struct propdata {
|
||||||
|
@ -95,6 +96,7 @@ struct atom_list {
|
||||||
- (void) request_event:(XSelectionRequestEvent *)e;
|
- (void) request_event:(XSelectionRequestEvent *)e;
|
||||||
- (void) notify_event:(XSelectionEvent *)e;
|
- (void) notify_event:(XSelectionEvent *)e;
|
||||||
- (void) property_event:(XPropertyEvent *)e;
|
- (void) property_event:(XPropertyEvent *)e;
|
||||||
|
- (void) xfixes_selection_notify:(XFixesSelectionNotifyEvent *)e;
|
||||||
- (void) handle_selection:(Atom)selection type:(Atom)type propdata:(struct propdata *)pdata;
|
- (void) handle_selection:(Atom)selection type:(Atom)type propdata:(struct propdata *)pdata;
|
||||||
- (void) claim_clipboard;
|
- (void) claim_clipboard;
|
||||||
- (BOOL) set_clipboard_manager_status:(BOOL)value;
|
- (BOOL) set_clipboard_manager_status:(BOOL)value;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#import <AppKit/NSBitmapImageRep.h>
|
#import <AppKit/NSBitmapImageRep.h>
|
||||||
|
|
||||||
|
#include <X11/extensions/xfixes.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The basic design of the pbproxy code is as follows.
|
* The basic design of the pbproxy code is as follows.
|
||||||
|
@ -56,12 +57,10 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
* 1. handle primary_on_grab
|
* 1. handle MULTIPLE - I need to study the ICCCM further.
|
||||||
* 2. handle MULTIPLE - I need to study the ICCCM further.
|
* 2. Handle PICT images properly.
|
||||||
* 3. Handle PICT images properly.
|
* 3. Handle NSPasteboard updates immediately, not on active/inactive
|
||||||
* 4. Handle NSPasteboard updates immediately, not on active/inactive
|
|
||||||
* - Open xterm, run 'cat readme.txt | pbcopy'
|
* - Open xterm, run 'cat readme.txt | pbcopy'
|
||||||
* 5. Detect if CLIPBOARD_MANAGER atom belongs to a dead client rather than just None
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -357,7 +356,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
|
||||||
|
|
||||||
XSetSelectionOwner (x_dpy, atoms->clipboard,
|
XSetSelectionOwner (x_dpy, atoms->clipboard,
|
||||||
_selection_window, timestamp);
|
_selection_window, timestamp);
|
||||||
XSetSelectionOwner (x_dpy, XA_PRIMARY,
|
XSetSelectionOwner (x_dpy, atoms->primary,
|
||||||
_selection_window, timestamp);
|
_selection_window, timestamp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -421,8 +420,8 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
|
||||||
if(owner == _selection_window)
|
if(owner == _selection_window)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if(None != _selection_window) {
|
if(owner != None) {
|
||||||
fprintf (stderr, "A clipboard manager is already running. pbproxy will not sync clipboard to pasteboard.\n");
|
fprintf (stderr, "A clipboard manager is already running on window 0x%x. pbproxy will not sync clipboard to pasteboard.\n", (int)owner);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,6 +1007,24 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) xfixes_selection_notify:(XFixesSelectionNotifyEvent *)e {
|
||||||
|
if(!pbproxy_prefs.active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(e->subtype) {
|
||||||
|
case XFixesSetSelectionOwnerNotify:
|
||||||
|
if(e->selection == atoms->primary && pbproxy_prefs.primary_on_grab)
|
||||||
|
[self x_copy:e->timestamp];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XFixesSelectionWindowDestroyNotify:
|
||||||
|
case XFixesSelectionClientCloseNotify:
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unhandled XFixesSelectionNotifyEvent: subtype=%d\n", e->subtype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) handle_targets: (Atom)selection propdata:(struct propdata *)pdata
|
- (void) handle_targets: (Atom)selection propdata:(struct propdata *)pdata
|
||||||
{
|
{
|
||||||
/* Find a type we can handle and prefer from the list of ATOMs. */
|
/* Find a type we can handle and prefer from the list of ATOMs. */
|
||||||
|
@ -1023,7 +1040,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
|
||||||
* This isn't required by the ICCCM, but some apps apparently
|
* This isn't required by the ICCCM, but some apps apparently
|
||||||
* don't respond to TARGETS properly.
|
* don't respond to TARGETS properly.
|
||||||
*/
|
*/
|
||||||
preferred = XA_STRING;
|
preferred = atoms->string;
|
||||||
}
|
}
|
||||||
|
|
||||||
DB ("requesting %s\n", XGetAtomName (x_dpy, preferred));
|
DB ("requesting %s\n", XGetAtomName (x_dpy, preferred));
|
||||||
|
@ -1261,6 +1278,11 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
|
||||||
pbproxy_prefs.pasteboard_to_primary = prefs_get_bool(CFSTR("sync_pasteboard_to_primary"), pbproxy_prefs.pasteboard_to_primary);
|
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);
|
pbproxy_prefs.pasteboard_to_clipboard = prefs_get_bool(CFSTR("sync_pasteboard_to_clipboard"), pbproxy_prefs.pasteboard_to_clipboard);
|
||||||
|
|
||||||
|
if(pbproxy_prefs.active && pbproxy_prefs.primary_on_grab && !have_xfixes) {
|
||||||
|
fprintf(stderr, "Disabling sync_primary_on_select functionality due to missing XFixes extension.\n");
|
||||||
|
pbproxy_prefs.primary_on_grab = NO;
|
||||||
|
}
|
||||||
|
|
||||||
/* Claim or release the CLIPBOARD_MANAGER atom */
|
/* Claim or release the CLIPBOARD_MANAGER atom */
|
||||||
if(![self set_clipboard_manager_status:(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)])
|
if(![self set_clipboard_manager_status:(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)])
|
||||||
pbproxy_prefs.clipboard_to_pasteboard = NO;
|
pbproxy_prefs.clipboard_to_pasteboard = NO;
|
||||||
|
@ -1335,6 +1357,10 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
|
||||||
pending_copy = 0;
|
pending_copy = 0;
|
||||||
pending_clipboard = 0;
|
pending_clipboard = 0;
|
||||||
|
|
||||||
|
if(have_xfixes)
|
||||||
|
XFixesSelectSelectionInput(x_dpy, _selection_window, atoms->primary,
|
||||||
|
XFixesSetSelectionOwnerNotifyMask);
|
||||||
|
|
||||||
[self reload_preferences];
|
[self reload_preferences];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user