forked from 12to11/12to11
Implement primary selections, and minor improvements elsewhere
* 12to11.c (XLMain): Initialize primary selections. Transfer between X and Wayland programs is still incomplete. * Imakefile (SRCS, OBJS): Add primary selection related objects and sources. (primary-selection-unstable-v1.h): (primary-selection-unstable-v1.c): New targets. * README: Update what is not supported. * compositor.h: New prototypes. * data_device.c (XLDataDeviceSendEnter): Handle resource allocation failures. * mime1.awk: Update generated code for changes in target entry structures. * seat.c (SetFocusSurface): Handle focus change for primary selections as well. (FindSurfaceUnder): Cut off fractional portion instead of rounding the given coordinates, so the correct surface is found when the cursor is moved just inside the rightmost pixel. * surface.c (XLSurfaceRunFrameCallbacks): Handle timestamp overflow. * xdata.c (struct _TargetMapping): Rename atom to atom_flag, and use it to store flags. (MappingAtom, MappingFlag, MappingIsNextDuplicate, MappingSetFlag) (MappingUnsetFlag, MappingIs): New macros. (struct _TargetMappingTable): New structure. (Duplicate): New definition. (direct_transfer): Update duplicate types. (mapping_table): New hash table. (HashMimeString, SetupMappingTable): New functions. (FindTranslationForMimeType, Receive): Use the target mapping table to look up targets instead. (CheckDuplicate): New function. (SendOffers): Call CheckDuplicates. (XLInitXData): Set up duplicate relationship between UTF8_STRING and is conversion entry, and the targets mapping table.
This commit is contained in:
parent
0965f5b3eb
commit
6c7801f0fd
9 changed files with 219 additions and 31 deletions
1
12to11.c
1
12to11.c
|
@ -155,6 +155,7 @@ XLMain (int argc, char **argv)
|
||||||
XLInitXData ();
|
XLInitXData ();
|
||||||
XLInitXSettings ();
|
XLInitXSettings ();
|
||||||
XLInitIconSurfaces ();
|
XLInitIconSurfaces ();
|
||||||
|
XLInitPrimarySelection ();
|
||||||
/* This has to come after the rest of the initialization. */
|
/* This has to come after the rest of the initialization. */
|
||||||
DetermineServerTime ();
|
DetermineServerTime ();
|
||||||
XLRunCompositor ();
|
XLRunCompositor ();
|
||||||
|
|
18
Imakefile
18
Imakefile
|
@ -21,14 +21,16 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
|
||||||
positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c \
|
positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c \
|
||||||
frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c \
|
frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c \
|
||||||
data_device.c xdg_popup.c linux-dmabuf-unstable-v1.c dmabuf.c \
|
data_device.c xdg_popup.c linux-dmabuf-unstable-v1.c dmabuf.c \
|
||||||
buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c
|
buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c \
|
||||||
|
primary-selection-unstable-v1.c primary_selection.c
|
||||||
|
|
||||||
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
xdg-shell.o surface.o region.o shm.o atoms.o subcompositor.o \
|
xdg-shell.o surface.o region.o shm.o atoms.o subcompositor.o \
|
||||||
positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o \
|
positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o \
|
||||||
frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o \
|
frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o \
|
||||||
data_device.o xdg_popup.o linux-dmabuf-unstable-v1.o dmabuf.o \
|
data_device.o xdg_popup.o linux-dmabuf-unstable-v1.o dmabuf.o \
|
||||||
buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o
|
buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o \
|
||||||
|
primary-selection-unstable-v1.o primary_selection.o
|
||||||
|
|
||||||
OPTIMIZE = -O0
|
OPTIMIZE = -O0
|
||||||
ANALYZE = -fanalyzer
|
ANALYZE = -fanalyzer
|
||||||
|
@ -53,7 +55,7 @@ CDEBUGFLAGS := -fno-common -Wall -Warith-conversion -Wdate-time \
|
||||||
$(ANALYZE)
|
$(ANALYZE)
|
||||||
|
|
||||||
short_types.txt: media_types.txt
|
short_types.txt: media_types.txt
|
||||||
XCOMM remove all data types starting with application/vnd.
|
XCOMM Remove all data types starting with application/vnd.
|
||||||
XCOMM no program really uses them in clipboard data, and they
|
XCOMM no program really uses them in clipboard data, and they
|
||||||
XCOMM waste a lot of space on disk.
|
XCOMM waste a lot of space on disk.
|
||||||
sed '/application\/vnd/d' media_types.txt > $@
|
sed '/application\/vnd/d' media_types.txt > $@
|
||||||
|
@ -81,9 +83,17 @@ xdg-shell.h: xdg-shell.xml
|
||||||
xdg-shell.c: xdg-shell.xml xdg-shell.h
|
xdg-shell.c: xdg-shell.xml xdg-shell.h
|
||||||
$(WAYLAND_SCANNER) private-code $< $@
|
$(WAYLAND_SCANNER) private-code $< $@
|
||||||
|
|
||||||
|
primary-selection-unstable-v1.h: primary-selection-unstable-v1.xml
|
||||||
|
$(WAYLAND_SCANNER) server-header $< $@
|
||||||
|
|
||||||
|
primary-selection-unstable-v1.c: primary-selection-unstable-v1.xml \
|
||||||
|
primary-selection-unstable-v1.h
|
||||||
|
$(WAYLAND_SCANNER) private-code $< $@
|
||||||
|
|
||||||
cleandir::
|
cleandir::
|
||||||
$(RM) linux-dmabuf-unstable-v1.c linux-dmabuf-unstable-v1.h \
|
$(RM) linux-dmabuf-unstable-v1.c linux-dmabuf-unstable-v1.h \
|
||||||
xdg-shell.c xdg-shell.h
|
xdg-shell.c xdg-shell.h primary-selection-unstable-v1.c \
|
||||||
|
primary-selection-unstable-v1.h
|
||||||
$(RM) transfer_atoms.h short_types.txt
|
$(RM) transfer_atoms.h short_types.txt
|
||||||
|
|
||||||
/* Undefine _BSD_SOURCE and _SVID_SOURCE, since both are deprecated
|
/* Undefine _BSD_SOURCE and _SVID_SOURCE, since both are deprecated
|
||||||
|
|
7
README
7
README
|
@ -42,14 +42,15 @@ complete degree:
|
||||||
'wl_seat', version: 7
|
'wl_seat', version: 7
|
||||||
'wl_data_device_manager', version: 3
|
'wl_data_device_manager', version: 3
|
||||||
'zwp_linux_dmabuf_v1', version: 4
|
'zwp_linux_dmabuf_v1', version: 4
|
||||||
|
'zwp_primary_selection_device_manager_v1', version: 1
|
||||||
|
|
||||||
With the main caveat being that zwp_linux_dmabuf_v1 has no real
|
With the main caveat being that zwp_linux_dmabuf_v1 has no real
|
||||||
support for multiple-provider setups (help wanted).
|
support for multiple-provider setups (help wanted).
|
||||||
|
|
||||||
Primary selections and window decorations are also not supported, even
|
Window decorations are also not supported, even though they fit in
|
||||||
though they fit in nicely with X window management.
|
nicely with X window management.
|
||||||
|
|
||||||
It would also be nice to have pinch gesture support in wl_pointer.
|
It would also be nice to have pinch gesture support.
|
||||||
|
|
||||||
This directory is organized as follows:
|
This directory is organized as follows:
|
||||||
|
|
||||||
|
|
|
@ -965,6 +965,11 @@ extern void XLInitIconSurfaces (void);
|
||||||
extern void XLReleaseIconSurface (IconSurface *);
|
extern void XLReleaseIconSurface (IconSurface *);
|
||||||
extern Bool XLIsWindowIconSurface (Window);
|
extern Bool XLIsWindowIconSurface (Window);
|
||||||
|
|
||||||
|
/* Defined in primary_selection.c. */
|
||||||
|
|
||||||
|
extern void XLInitPrimarySelection (void);
|
||||||
|
extern void XLPrimarySelectionHandleFocusChange (Seat *);
|
||||||
|
|
||||||
/* Utility functions that don't belong in a specific file. */
|
/* Utility functions that don't belong in a specific file. */
|
||||||
|
|
||||||
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
||||||
|
|
|
@ -1364,6 +1364,11 @@ XLDataDeviceSendEnter (Seat *seat, Surface *surface, double x, double y,
|
||||||
/* First, create a data offer corresponding to the data
|
/* First, create a data offer corresponding to the data
|
||||||
source if it exists. */
|
source if it exists. */
|
||||||
resource = AddDataOffer (client, source);
|
resource = AddDataOffer (client, source);
|
||||||
|
|
||||||
|
if (!resource)
|
||||||
|
/* Allocation of the resource failed. */
|
||||||
|
goto next;
|
||||||
|
|
||||||
offer = wl_resource_get_user_data (resource);
|
offer = wl_resource_get_user_data (resource);
|
||||||
offer->dnd_serial = serial;
|
offer->dnd_serial = serial;
|
||||||
offer->last_action = -1;
|
offer->last_action = -1;
|
||||||
|
@ -1397,6 +1402,7 @@ XLDataDeviceSendEnter (Seat *seat, Surface *surface, double x, double y,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
reference = reference->next;
|
reference = reference->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ BEGIN {
|
||||||
match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array)
|
match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array)
|
||||||
name = array[1]
|
name = array[1]
|
||||||
gsub (/[[:punct:]]/, "_", name) # Convert to a valid atom name
|
gsub (/[[:punct:]]/, "_", name) # Convert to a valid atom name
|
||||||
printf " table[%d + start].atom = %s;\\\n", i++, name
|
printf " table[%d + start].atom_flag = %s;\\\n", i++, name
|
||||||
}
|
}
|
||||||
|
|
||||||
END {
|
END {
|
||||||
|
|
13
seat.c
13
seat.c
|
@ -2625,7 +2625,12 @@ SetFocusSurface (Seat *seat, Surface *focus)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!focus)
|
if (!focus)
|
||||||
|
{
|
||||||
|
/* These changes must be handled even if there is no more focus
|
||||||
|
surface. */
|
||||||
|
XLPrimarySelectionHandleFocusChange (seat);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
seat->focus_surface = focus;
|
seat->focus_surface = focus;
|
||||||
seat->focus_destroy_callback
|
seat->focus_destroy_callback
|
||||||
|
@ -2633,6 +2638,8 @@ SetFocusSurface (Seat *seat, Surface *focus)
|
||||||
|
|
||||||
SendKeyboardEnter (seat, focus);
|
SendKeyboardEnter (seat, focus);
|
||||||
|
|
||||||
|
XLPrimarySelectionHandleFocusChange (seat);
|
||||||
|
|
||||||
if (seat->data_device)
|
if (seat->data_device)
|
||||||
XLDataDeviceHandleFocusChange (seat->data_device);
|
XLDataDeviceHandleFocusChange (seat->data_device);
|
||||||
}
|
}
|
||||||
|
@ -2670,8 +2677,10 @@ FindSurfaceUnder (Subcompositor *subcompositor, double x, double y)
|
||||||
int x_off, y_off;
|
int x_off, y_off;
|
||||||
View *view;
|
View *view;
|
||||||
|
|
||||||
view = SubcompositorLookupView (subcompositor, lrint (x),
|
/* Do not round these figures. Instead, cut off the fractional,
|
||||||
lrint (y), &x_off, &y_off);
|
like the X server does when deciding when to set the cursor. */
|
||||||
|
view = SubcompositorLookupView (subcompositor, x, y,
|
||||||
|
&x_off, &y_off);
|
||||||
|
|
||||||
if (view)
|
if (view)
|
||||||
return ViewGetData (view);
|
return ViewGetData (view);
|
||||||
|
|
|
@ -1167,7 +1167,13 @@ XLSurfaceRunFrameCallbacks (Surface *surface, struct timespec time)
|
||||||
uint32_t ms_time;
|
uint32_t ms_time;
|
||||||
XLList *list;
|
XLList *list;
|
||||||
|
|
||||||
ms_time = time.tv_sec * 1000 + time.tv_nsec / 1000000;
|
/* I don't know what else is reasonable in case of overflow. */
|
||||||
|
|
||||||
|
if (IntMultiplyWrapv (time.tv_sec, 1000, &ms_time))
|
||||||
|
ms_time = UINT32_MAX;
|
||||||
|
else if (IntAddWrapv (ms_time, time.tv_nsec / 1000000,
|
||||||
|
&ms_time))
|
||||||
|
ms_time = UINT32_MAX;
|
||||||
|
|
||||||
RunFrameCallbacks (&surface->current_state.frame_callbacks,
|
RunFrameCallbacks (&surface->current_state.frame_callbacks,
|
||||||
ms_time);
|
ms_time);
|
||||||
|
|
182
xdata.c
182
xdata.c
|
@ -42,6 +42,7 @@ typedef struct _ConversionTransferInfo ConversionTransferInfo;
|
||||||
typedef struct _WriteInfo WriteInfo;
|
typedef struct _WriteInfo WriteInfo;
|
||||||
typedef struct _ConversionWriteInfo ConversionWriteInfo;
|
typedef struct _ConversionWriteInfo ConversionWriteInfo;
|
||||||
typedef struct _DataConversion DataConversion;
|
typedef struct _DataConversion DataConversion;
|
||||||
|
typedef struct _TargetMappingTable TargetMappingTable;
|
||||||
|
|
||||||
struct _ReadTargetsData
|
struct _ReadTargetsData
|
||||||
{
|
{
|
||||||
|
@ -54,8 +55,12 @@ struct _ReadTargetsData
|
||||||
|
|
||||||
struct _TargetMapping
|
struct _TargetMapping
|
||||||
{
|
{
|
||||||
/* The atom of the X target. */
|
/* The atom of the X target. The top 3 bits of an XID are
|
||||||
Atom atom;
|
guaranteed to be 0, so the 31st bit is used to store a flag
|
||||||
|
meaning that the next entry is a duplicate of this one, and the
|
||||||
|
30th bit is used to store a flag containing state used by
|
||||||
|
SendOffers. */
|
||||||
|
Atom atom_flag;
|
||||||
|
|
||||||
/* The name of the Wayland MIME type. */
|
/* The name of the Wayland MIME type. */
|
||||||
const char *mime_type;
|
const char *mime_type;
|
||||||
|
@ -64,6 +69,13 @@ struct _TargetMapping
|
||||||
void (*translation_func) (Time, Atom, Atom, int);
|
void (*translation_func) (Time, Atom, Atom, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MappingAtom(mapping) ((mapping)->atom_flag & 0x1fffffff)
|
||||||
|
#define MappingFlag(mapping) ((mapping)->atom_flag & (1 << 29))
|
||||||
|
#define MappingIsNextDuplicate(mapping) ((mapping)->atom_flag & (1 << 30))
|
||||||
|
#define MappingSetFlag(mapping) ((mapping)->atom_flag |= (1 << 29))
|
||||||
|
#define MappingUnsetFlag(mapping) ((mapping)->atom_flag &= ~(1 << 29))
|
||||||
|
#define MappingIs(mapping, atom) (MappingAtom (mapping) == (atom))
|
||||||
|
|
||||||
struct _DataConversion
|
struct _DataConversion
|
||||||
{
|
{
|
||||||
/* The MIME type of the Wayland offer. */
|
/* The MIME type of the Wayland offer. */
|
||||||
|
@ -179,20 +191,43 @@ struct _ConversionWriteInfo
|
||||||
iconv_t cd;
|
iconv_t cd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _TargetMappingTable
|
||||||
|
{
|
||||||
|
/* Array of indices into direct_transfer. */
|
||||||
|
unsigned short *buckets[32];
|
||||||
|
|
||||||
|
/* Number of elements in each array. */
|
||||||
|
unsigned short n_elements[32];
|
||||||
|
|
||||||
|
/* Array of indices into direct_transfer. */
|
||||||
|
unsigned short *atom_buckets[16];
|
||||||
|
|
||||||
|
/* Number of elements in each array. */
|
||||||
|
unsigned short n_atom_elements[16];
|
||||||
|
};
|
||||||
|
|
||||||
/* Base event code of the Xfixes extension. */
|
/* Base event code of the Xfixes extension. */
|
||||||
static int fixes_event_base;
|
static int fixes_event_base;
|
||||||
|
|
||||||
|
/* This means the next item in the targets mapping table has the same
|
||||||
|
MIME type as this one. */
|
||||||
|
|
||||||
|
#define Duplicate (1U << 30)
|
||||||
|
|
||||||
/* Map of targets that can be transferred from X to Wayland clients
|
/* Map of targets that can be transferred from X to Wayland clients
|
||||||
and vice versa. */
|
and vice versa. */
|
||||||
static TargetMapping direct_transfer[] =
|
static TargetMapping direct_transfer[] =
|
||||||
{
|
{
|
||||||
{ XA_STRING, "text/plain;charset=iso-9889-1" },
|
{ XA_STRING, "text/plain;charset=iso-9889-1" },
|
||||||
{ 0, "text/plain;charset=utf-8" },
|
{ Duplicate, "text/plain;charset=utf-8" },
|
||||||
{ XA_STRING, "text/plain;charset=utf-8" },
|
{ XA_STRING, "text/plain;charset=utf-8" },
|
||||||
/* These mappings are automatically generated. */
|
/* These mappings are automatically generated. */
|
||||||
DirectTransferMappings
|
DirectTransferMappings
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Lookup table for such mappings. */
|
||||||
|
static TargetMappingTable mapping_table;
|
||||||
|
|
||||||
/* Map of Wayland offer types to X atoms and data conversion
|
/* Map of Wayland offer types to X atoms and data conversion
|
||||||
functions. */
|
functions. */
|
||||||
static DataConversion data_conversions[] =
|
static DataConversion data_conversions[] =
|
||||||
|
@ -244,6 +279,53 @@ Accept (struct wl_client *client, struct wl_resource *resource,
|
||||||
/* Nothing has to be done here yet. */
|
/* Nothing has to be done here yet. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
HashMimeString (const char *string)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
i = 3323198485ul;
|
||||||
|
for (; *string; ++string)
|
||||||
|
{
|
||||||
|
i ^= *string;
|
||||||
|
i *= 0x5bd1e995;
|
||||||
|
i ^= i >> 15;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SetupMappingTable (void)
|
||||||
|
{
|
||||||
|
unsigned int idx, i, nelements;
|
||||||
|
|
||||||
|
/* This is needed for the atoms table, since the atom indices are
|
||||||
|
determined by the X server. */
|
||||||
|
XLAssert (ArrayElements (direct_transfer) <= USHRT_MAX);
|
||||||
|
|
||||||
|
for (i = 0; i < ArrayElements (direct_transfer); ++i)
|
||||||
|
{
|
||||||
|
idx = HashMimeString (direct_transfer[i].mime_type) % 32;
|
||||||
|
|
||||||
|
nelements = ++mapping_table.n_elements[idx];
|
||||||
|
mapping_table.buckets[idx]
|
||||||
|
= XLRealloc (mapping_table.buckets[idx],
|
||||||
|
nelements * sizeof (unsigned short));
|
||||||
|
mapping_table.buckets[idx][nelements - 1] = i;
|
||||||
|
|
||||||
|
/* Now, set up the lookup table indexed by atoms. It is faster
|
||||||
|
to compare atoms than strings, so the table is smaller. */
|
||||||
|
|
||||||
|
idx = MappingAtom (&direct_transfer[i]) % 16;
|
||||||
|
|
||||||
|
nelements = ++mapping_table.n_atom_elements[idx];
|
||||||
|
mapping_table.atom_buckets[idx]
|
||||||
|
= XLRealloc (mapping_table.atom_buckets[idx],
|
||||||
|
nelements * sizeof (unsigned short));
|
||||||
|
mapping_table.atom_buckets[idx][nelements - 1] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
HasSelectionTarget (Atom atom)
|
HasSelectionTarget (Atom atom)
|
||||||
{
|
{
|
||||||
|
@ -261,13 +343,18 @@ HasSelectionTarget (Atom atom)
|
||||||
static TargetMapping *
|
static TargetMapping *
|
||||||
FindTranslationForMimeType (const char *mime_type)
|
FindTranslationForMimeType (const char *mime_type)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned short *buckets, i;
|
||||||
|
unsigned int idx;
|
||||||
|
|
||||||
for (i = 0; i < ArrayElements (direct_transfer); ++i)
|
idx = HashMimeString (mime_type) % 32;
|
||||||
|
buckets = mapping_table.buckets[idx];
|
||||||
|
|
||||||
|
for (i = 0; i < mapping_table.n_elements[idx]; ++i)
|
||||||
{
|
{
|
||||||
if (!strcmp (direct_transfer[i].mime_type, mime_type)
|
if (!strcmp (direct_transfer[buckets[i]].mime_type,
|
||||||
&& HasSelectionTarget (direct_transfer[i].atom))
|
mime_type)
|
||||||
return &direct_transfer[i];
|
&& HasSelectionTarget (MappingAtom (&direct_transfer[buckets[i]])))
|
||||||
|
return &direct_transfer[buckets[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -575,11 +662,13 @@ Receive (struct wl_client *client, struct wl_resource *resource,
|
||||||
{
|
{
|
||||||
if (!translation->translation_func)
|
if (!translation->translation_func)
|
||||||
/* If a corresponding target exists, ask to receive it. */
|
/* If a corresponding target exists, ask to receive it. */
|
||||||
PostReceiveDirect (time, CLIPBOARD, translation->atom, fd);
|
PostReceiveDirect (time, CLIPBOARD,
|
||||||
|
MappingAtom (translation), fd);
|
||||||
else
|
else
|
||||||
/* Otherwise, use the translation function. */
|
/* Otherwise, use the translation function. */
|
||||||
translation->translation_func (time, CLIPBOARD,
|
translation->translation_func (time, CLIPBOARD,
|
||||||
translation->atom, fd);
|
MappingAtom (translation),
|
||||||
|
fd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
close (fd);
|
close (fd);
|
||||||
|
@ -632,10 +721,55 @@ CreateOffer (struct wl_client *client, Time time)
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
CheckDuplicate (unsigned short index, Atom a)
|
||||||
|
{
|
||||||
|
TargetMapping *start;
|
||||||
|
|
||||||
|
start = &direct_transfer[index];
|
||||||
|
|
||||||
|
/* If the flag is already set, then this type has already been
|
||||||
|
sent. */
|
||||||
|
if (MappingFlag (start))
|
||||||
|
return False;
|
||||||
|
|
||||||
|
/* Set this entry's duplicate flag. */
|
||||||
|
MappingSetFlag (start);
|
||||||
|
|
||||||
|
/* As long as the next index still refers to a duplicate of this
|
||||||
|
item, set its duplicate flag. */
|
||||||
|
|
||||||
|
while (MappingIsNextDuplicate (start))
|
||||||
|
MappingSetFlag (++start);
|
||||||
|
|
||||||
|
/* Do the same backwards. */
|
||||||
|
|
||||||
|
if (index)
|
||||||
|
{
|
||||||
|
start = &direct_transfer[index - 1];
|
||||||
|
|
||||||
|
while (MappingIsNextDuplicate (start))
|
||||||
|
{
|
||||||
|
MappingSetFlag (start);
|
||||||
|
|
||||||
|
/* If this is now the start of the target mapping table,
|
||||||
|
break. */
|
||||||
|
if (start == direct_transfer)
|
||||||
|
break;
|
||||||
|
|
||||||
|
start--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SendOffers (struct wl_resource *resource, Time time)
|
SendOffers (struct wl_resource *resource, Time time)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
unsigned int idx;
|
||||||
|
unsigned short *buckets;
|
||||||
|
|
||||||
if (time < last_x_selection_change)
|
if (time < last_x_selection_change)
|
||||||
/* This offer is out of date. */
|
/* This offer is out of date. */
|
||||||
|
@ -644,16 +778,29 @@ SendOffers (struct wl_resource *resource, Time time)
|
||||||
for (i = 0; i < num_x_selection_targets; ++i)
|
for (i = 0; i < num_x_selection_targets; ++i)
|
||||||
{
|
{
|
||||||
/* Offer each type corresponding to this target. */
|
/* Offer each type corresponding to this target. */
|
||||||
|
idx = x_selection_targets[i] % 16;
|
||||||
|
|
||||||
for (j = 0; j < ArrayElements (direct_transfer); ++j)
|
/* N.B. that duplicates do appear in the atom buckets, which
|
||||||
|
is intentional. */
|
||||||
|
buckets = mapping_table.atom_buckets[idx];
|
||||||
|
|
||||||
|
for (j = 0; j < mapping_table.n_atom_elements[idx]; ++j)
|
||||||
{
|
{
|
||||||
if (direct_transfer[j].atom == x_selection_targets[i])
|
if (MappingIs (&direct_transfer[buckets[j]],
|
||||||
/* If it exists, offer it to the client. TODO: handle
|
x_selection_targets[i])
|
||||||
duplicates. */
|
&& CheckDuplicate (buckets[j],
|
||||||
|
x_selection_targets[i]))
|
||||||
|
/* If it exists and was not previously offered, offer it
|
||||||
|
to the client. */
|
||||||
wl_data_offer_send_offer (resource,
|
wl_data_offer_send_offer (resource,
|
||||||
direct_transfer[j].mime_type);
|
direct_transfer[buckets[j]].mime_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear the duplicate flag of each item in the targets table that
|
||||||
|
was touched. */
|
||||||
|
for (i = 0; i < ArrayElements (direct_transfer); ++i)
|
||||||
|
MappingUnsetFlag (&direct_transfer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1751,10 +1898,13 @@ XLInitXData (void)
|
||||||
SelectSelectionInput (CLIPBOARD);
|
SelectSelectionInput (CLIPBOARD);
|
||||||
|
|
||||||
/* Initialize atoms used in the direct transfer table. */
|
/* Initialize atoms used in the direct transfer table. */
|
||||||
direct_transfer[1].atom = UTF8_STRING;
|
direct_transfer[1].atom_flag = UTF8_STRING | Duplicate;
|
||||||
direct_transfer[2].translation_func = PostReceiveConversion;
|
direct_transfer[2].translation_func = PostReceiveConversion;
|
||||||
DirectTransferInitializer (direct_transfer, 3);
|
DirectTransferInitializer (direct_transfer, 3);
|
||||||
|
|
||||||
|
/* Set up the direct transfer table. */
|
||||||
|
SetupMappingTable ();
|
||||||
|
|
||||||
/* And those used in the data conversions table. */
|
/* And those used in the data conversions table. */
|
||||||
data_conversions[0].atom = UTF8_STRING;
|
data_conversions[0].atom = UTF8_STRING;
|
||||||
data_conversions[0].type = UTF8_STRING;
|
data_conversions[0].type = UTF8_STRING;
|
||||||
|
|
Loading…
Add table
Reference in a new issue