Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
9fff718a
Commit
9fff718a
authored
Sep 01, 2004
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wineclipsrv is no longer used, remove it.
parent
8bc2fdb3
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
2 additions
and
1215 deletions
+2
-1215
.cvsignore
dlls/x11drv/.cvsignore
+0
-1
Makefile.in
dlls/x11drv/Makefile.in
+0
-13
wineclipsrv.c
dlls/x11drv/wineclipsrv.c
+0
-1188
PACKAGING
documentation/PACKAGING
+2
-7
config
documentation/samples/config
+0
-1
wine.man.in
documentation/wine.man.in
+0
-5
No files found.
dlls/x11drv/.cvsignore
View file @
9fff718a
Makefile
wineclipsrv
x11drv.dll.dbg.c
x11drv.spec.def
dlls/x11drv/Makefile.in
View file @
9fff718a
EXTRADEFS
=
-DBINDIR
=
"
\"
$(bindir)
\"
"
TOPSRCDIR
=
@top_srcdir@
TOPOBJDIR
=
../..
SRCDIR
=
@srcdir@
...
...
@@ -44,20 +43,8 @@ C_SRCS = \
xrender.c
\
xvidmode.c
PROGRAMS
=
wineclipsrv
@MAKE_DLL_RULES@
all
:
$(PROGRAMS)
wineclipsrv
:
wineclipsrv.c
$(CC)
$(ALLCFLAGS)
-o
wineclipsrv
$(SRCDIR)
/wineclipsrv.c
$(EXTRALIBS)
$(LDFLAGS)
$(LIBS)
install
::
$(PROGRAMS)
$(MKINSTALLDIRS)
$(bindir)
$(INSTALL_PROGRAM)
wineclipsrv
$(bindir)
/wineclipsrv
uninstall
::
$(RM)
$(bindir)
/wineclipsrv
### Dependencies:
dlls/x11drv/wineclipsrv.c
deleted
100644 → 0
View file @
8bc2fdb3
/*
* Wine Clipboard Server
*
* Copyright 1999 Noel Borthwick
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* USAGE:
* wineclipsrv [selection_mask] [debugClass_mask] [clearAllSelections]
*
* The optional selection-mask argument is a bit mask of the selection
* types to be acquired. Currently two selections are supported:
* 1. PRIMARY (mask value 1)
* 2. CLIPBOARD (mask value 2).
*
* debugClass_mask is a bit mask of all debugging classes for which messages
* are to be output. The standard Wine debug class set FIXME(1), ERR(2),
* WARN(4) and TRACE(8) are supported.
*
* If clearAllSelections == 1 *all* selections are lost whenever a SelectionClear
* event is received.
*
* If no arguments are supplied the server aquires all selections. (mask value 3)
* and defaults to output of only FIXME(1) and ERR(2) messages. The default for
* clearAllSelections is 0.
*
* NOTES:
*
* The Wine Clipboard Server is a standalone XLib application whose
* purpose is to manage the X selection when Wine exits.
* The server itself is started automatically with the appropriate
* selection masks, whenever Wine exits after acquiring the PRIMARY and/or
* CLIPBOARD selection. (See X11DRV_CLIPBOARD_ResetOwner)
* When the server starts, it first proceeds to capture the selection data from
* Wine and then takes over the selection ownership. It does this by querying
* the current selection owner(of the specified selections) for the TARGETS
* selection target. It then proceeds to cache all the formats exposed by
* TARGETS. If the selection does not support the TARGETS target, or if no
* target formats are exposed, the server simply exits.
* Once the cache has been filled, the server then actually acquires ownership
* of the respective selection and begins fielding selection requests.
* Selection requests are serviced from the cache. If a selection is lost the
* server flushes its internal cache, destroying all data previously saved.
* Once ALL selections have been lost the server terminates.
*
* TODO:
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
/*
* Lightweight debug definitions for Wine Clipboard Server.
* The standard FIXME, ERR, WARN & TRACE classes are supported
* without debug channels.
* The standard defines NO_TRACE_MSGS and NO_DEBUG_MSGS will compile out
* TRACE, WARN and ERR and FIXME message displays.
*/
/* Internal definitions (do not use these directly) */
#ifdef __SUNPRO_C
#define __FUNCTION__ __func__
#endif
enum
__DEBUG_CLASS
{
__DBCL_FIXME
,
__DBCL_ERR
,
__DBCL_WARN
,
__DBCL_TRACE
,
__DBCL_COUNT
};
extern
char
__debug_msg_enabled
[
__DBCL_COUNT
];
extern
const
char
*
const
debug_cl_name
[
__DBCL_COUNT
];
#define DEBUG_CLASS_COUNT __DBCL_COUNT
#define __GET_DEBUGGING(dbcl) (__debug_msg_enabled[(dbcl)])
#define __SET_DEBUGGING(dbcl,on) (__debug_msg_enabled[(dbcl)] = (on))
#define __DPRINTF(dbcl) \
(!__GET_DEBUGGING(dbcl) || \
(printf("%s:%s:%s ", debug_cl_name[(dbcl)], progname, __FUNCTION__),0)) \
? 0 : printf
#define __DUMMY_DPRINTF 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
/* use configure to allow user to compile out debugging messages */
#ifndef NO_TRACE_MSGS
#define TRACE __DPRINTF(__DBCL_TRACE)
#else
#define TRACE __DUMMY_DPRINTF
#endif
/* NO_TRACE_MSGS */
#ifndef NO_DEBUG_MSGS
#define WARN __DPRINTF(__DBCL_WARN)
#define FIXME __DPRINTF(__DBCL_FIXME)
#else
#define WARN __DUMMY_DPRINTF
#define FIXME __DUMMY_DPRINTF
#endif
/* NO_DEBUG_MSGS */
/* define error macro regardless of what is configured */
#define ERR __DPRINTF(__DBCL_ERR)
#define TRUE 1
#define FALSE 0
typedef
int
BOOL
;
/* Internal definitions for debugging messages(do not use these directly) */
const
char
*
const
debug_cl_name
[]
=
{
"fixme"
,
"err"
,
"warn"
,
"trace"
};
char
__debug_msg_enabled
[
DEBUG_CLASS_COUNT
]
=
{
1
,
1
,
0
,
0
};
/* Selection masks */
#define S_NOSELECTION 0
#define S_PRIMARY 1
#define S_CLIPBOARD 2
/* Debugging class masks */
#define C_FIXME 1
#define C_ERR 2
#define C_WARN 4
#define C_TRACE 8
/*
* Global variables
*/
static
Display
*
g_display
=
NULL
;
static
int
screen_num
;
static
char
*
progname
;
/* name this program was invoked by */
static
Window
g_win
=
0
;
/* the hidden clipboard server window */
static
GC
g_gc
=
0
;
static
const
char
g_szOutOfMemory
[]
=
"Insufficient memory!
\n
"
;
/* X selection context info */
static
const
char
_CLIPBOARD
[]
=
"CLIPBOARD"
;
/* CLIPBOARD atom name */
static
int
g_selectionToAcquire
=
0
;
/* Masks for the selection to be acquired */
static
int
g_selectionAcquired
=
0
;
/* Contains the current selection masks */
static
int
g_clearAllSelections
=
0
;
/* If TRUE *all* selections are lost on SelectionClear */
/* Selection cache */
typedef
struct
tag_CACHEENTRY
{
Atom
target
;
Atom
type
;
int
nFormat
;
int
nElements
;
void
*
pData
;
}
CACHEENTRY
,
*
PCACHEENTRY
;
static
PCACHEENTRY
g_pPrimaryCache
=
NULL
;
/* Primary selection cache */
static
PCACHEENTRY
g_pClipboardCache
=
NULL
;
/* Clipboard selection cache */
static
unsigned
long
g_cPrimaryTargets
=
0
;
/* Number of TARGETS reported by PRIMARY selection */
static
unsigned
long
g_cClipboardTargets
=
0
;
/* Number of TARGETS reported by CLIPBOARD selection */
/*
* Prototypes
*/
int
RunAsDaemon
(
void
);
BOOL
Init
(
int
argc
,
char
**
argv
);
void
TerminateServer
(
int
ret
);
int
AcquireSelection
();
int
CacheDataFormats
(
Atom
SelectionSrc
,
PCACHEENTRY
*
ppCache
);
void
EmptyCache
(
PCACHEENTRY
pCache
,
int
nItems
);
BOOL
FillCacheEntry
(
Atom
SelectionSrc
,
Atom
target
,
PCACHEENTRY
pCacheEntry
);
BOOL
LookupCacheItem
(
Atom
selection
,
Atom
target
,
PCACHEENTRY
*
ppCacheEntry
);
void
EVENT_ProcessEvent
(
XEvent
*
event
);
Atom
EVENT_SelectionRequest_MULTIPLE
(
XSelectionRequestEvent
*
pevent
);
void
EVENT_SelectionRequest
(
XSelectionRequestEvent
*
event
,
BOOL
bIsMultiple
);
void
EVENT_SelectionClear
(
XSelectionClearEvent
*
event
);
void
EVENT_PropertyNotify
(
XPropertyEvent
*
event
);
Pixmap
DuplicatePixmap
(
Pixmap
pixmap
);
void
TextOut
(
Window
win
,
GC
gc
,
char
*
pStr
);
void
getGC
(
Window
win
,
GC
*
gc
);
int
main
(
int
argc
,
char
**
argv
)
{
XEvent
event
;
if
(
RunAsDaemon
()
==
-
1
)
{
ERR
(
"could not run as daemon
\n
"
);
exit
(
1
);
}
if
(
!
Init
(
argc
,
argv
)
)
exit
(
0
);
/* Acquire the selection after retrieving all clipboard data
* owned by the current selection owner. If we were unable to
* Acquire any selection, terminate right away.
*/
if
(
AcquireSelection
()
==
S_NOSELECTION
)
TerminateServer
(
0
);
TRACE
(
"Clipboard server running...
\n
"
);
/* Start an X event loop */
while
(
1
)
{
XNextEvent
(
g_display
,
&
event
);
EVENT_ProcessEvent
(
&
event
);
}
}
/**************************************************************************
* RunAsDaemon()
*/
int
RunAsDaemon
(
void
)
{
int
i
;
/* fork child process and let parent exit ; gets rid of original PID */
switch
(
fork
()
)
{
case
-
1
:
ERR
(
"fork failed
\n
"
);
return
(
-
1
);
case
0
:
exit
(
0
);
break
;
}
/* below is child process w/ new PID, set as session leader */
setsid
();
/* close stdin,stdout,stderr and file descriptors (overkill method) */
for
(
i
=
0
;
i
<
256
;
i
++
)
close
(
i
);
TRACE
(
"now running as daemon...
\n
"
);
return
0
;
}
/**************************************************************************
* Init()
* Initialize the clipboard server
*/
BOOL
Init
(
int
argc
,
char
**
argv
)
{
unsigned
int
width
,
height
;
/* window size */
unsigned
int
border_width
=
4
;
/* four pixels */
unsigned
int
display_width
,
display_height
;
char
*
window_name
=
"Wine Clipboard Server"
;
XSizeHints
*
size_hints
=
NULL
;
XWMHints
*
wm_hints
=
NULL
;
XClassHint
*
class_hints
=
NULL
;
XTextProperty
windowName
;
char
*
display_name
=
NULL
;
progname
=
argv
[
0
];
if
(
!
(
size_hints
=
XAllocSizeHints
()))
{
ERR
(
g_szOutOfMemory
);
return
0
;
}
if
(
!
(
wm_hints
=
XAllocWMHints
()))
{
ERR
(
g_szOutOfMemory
);
return
0
;
}
if
(
!
(
class_hints
=
XAllocClassHint
()))
{
ERR
(
g_szOutOfMemory
);
return
0
;
}
/* connect to X server */
if
(
(
g_display
=
XOpenDisplay
(
display_name
))
==
NULL
)
{
ERR
(
"cannot connect to X server %s
\n
"
,
XDisplayName
(
display_name
));
return
0
;
}
/* get screen size from display structure macro */
screen_num
=
DefaultScreen
(
g_display
);
display_width
=
DisplayWidth
(
g_display
,
screen_num
);
display_height
=
DisplayHeight
(
g_display
,
screen_num
);
/* size window with enough room for text */
width
=
display_width
/
3
,
height
=
display_height
/
4
;
/* create opaque window */
g_win
=
XCreateSimpleWindow
(
g_display
,
RootWindow
(
g_display
,
screen_num
),
0
,
0
,
width
,
height
,
border_width
,
BlackPixel
(
g_display
,
screen_num
),
WhitePixel
(
g_display
,
screen_num
));
/* Set size hints for window manager. The window manager may
* override these settings. */
/* x, y, width, and height hints are now taken from
* the actual settings of the window when mapped. Note
* that PPosition and PSize must be specified anyway. */
size_hints
->
flags
=
PPosition
|
PSize
|
PMinSize
;
size_hints
->
min_width
=
300
;
size_hints
->
min_height
=
200
;
/* These calls store window_name into XTextProperty structures
* and sets the other fields properly. */
if
(
XStringListToTextProperty
(
&
window_name
,
1
,
&
windowName
)
==
0
)
{
ERR
(
"structure allocation for windowName failed.
\n
"
);
TerminateServer
(
-
1
);
}
wm_hints
->
initial_state
=
NormalState
;
wm_hints
->
input
=
True
;
wm_hints
->
flags
=
StateHint
|
InputHint
;
class_hints
->
res_name
=
progname
;
class_hints
->
res_class
=
"WineClipSrv"
;
XSetWMProperties
(
g_display
,
g_win
,
&
windowName
,
NULL
,
argv
,
argc
,
size_hints
,
wm_hints
,
class_hints
);
/* Select event types wanted */
XSelectInput
(
g_display
,
g_win
,
ExposureMask
|
KeyPressMask
|
ButtonPressMask
|
StructureNotifyMask
|
PropertyChangeMask
);
/* create GC for text and drawing */
getGC
(
g_win
,
&
g_gc
);
/* Display window */
/* XMapWindow(g_display, g_win); */
/* Set the selections to be acquired from the command line argument.
* If none specified, default to all selections we understand.
*/
if
(
argc
>
1
)
g_selectionToAcquire
=
atoi
(
argv
[
1
]);
else
g_selectionToAcquire
=
S_PRIMARY
|
S_CLIPBOARD
;
/* Set the debugging class state from the command line argument */
if
(
argc
>
2
)
{
int
dbgClasses
=
atoi
(
argv
[
2
]);
__SET_DEBUGGING
(
__DBCL_FIXME
,
dbgClasses
&
C_FIXME
);
__SET_DEBUGGING
(
__DBCL_ERR
,
dbgClasses
&
C_ERR
);
__SET_DEBUGGING
(
__DBCL_WARN
,
dbgClasses
&
C_WARN
);
__SET_DEBUGGING
(
__DBCL_TRACE
,
dbgClasses
&
C_TRACE
);
}
/* Set the "ClearSelections" state from the command line argument */
if
(
argc
>
3
)
g_clearAllSelections
=
atoi
(
argv
[
3
]);
return
TRUE
;
}
/**************************************************************************
* TerminateServer()
*/
void
TerminateServer
(
int
ret
)
{
TRACE
(
"Terminating Wine clipboard server...
\n
"
);
/* Free Primary and Clipboard selection caches */
EmptyCache
(
g_pPrimaryCache
,
g_cPrimaryTargets
);
EmptyCache
(
g_pClipboardCache
,
g_cClipboardTargets
);
if
(
g_gc
)
XFreeGC
(
g_display
,
g_gc
);
if
(
g_display
)
XCloseDisplay
(
g_display
);
exit
(
ret
);
}
/**************************************************************************
* AcquireSelection()
*
* Acquire the selection after retrieving all clipboard data owned by
* the current selection owner.
*/
int
AcquireSelection
()
{
Atom
xaClipboard
=
XInternAtom
(
g_display
,
_CLIPBOARD
,
False
);
/*
* For all selections we need to acquire, get a list of all targets
* supplied by the current selection owner.
*/
if
(
g_selectionToAcquire
&
S_PRIMARY
)
{
TRACE
(
"Acquiring PRIMARY selection...
\n
"
);
g_cPrimaryTargets
=
CacheDataFormats
(
XA_PRIMARY
,
&
g_pPrimaryCache
);
TRACE
(
"Cached %ld formats...
\n
"
,
g_cPrimaryTargets
);
}
if
(
g_selectionToAcquire
&
S_CLIPBOARD
)
{
TRACE
(
"Acquiring CLIPBOARD selection...
\n
"
);
g_cClipboardTargets
=
CacheDataFormats
(
xaClipboard
,
&
g_pClipboardCache
);
TRACE
(
"Cached %ld formats...
\n
"
,
g_cClipboardTargets
);
}
/*
* Now that we have cached the data, we proceed to acquire the selections
*/
if
(
g_cPrimaryTargets
)
{
/* Acquire the PRIMARY selection */
while
(
XGetSelectionOwner
(
g_display
,
XA_PRIMARY
)
!=
g_win
)
XSetSelectionOwner
(
g_display
,
XA_PRIMARY
,
g_win
,
CurrentTime
);
g_selectionAcquired
|=
S_PRIMARY
;
}
else
TRACE
(
"No PRIMARY targets - ownership not acquired.
\n
"
);
if
(
g_cClipboardTargets
)
{
/* Acquire the CLIPBOARD selection */
while
(
XGetSelectionOwner
(
g_display
,
xaClipboard
)
!=
g_win
)
XSetSelectionOwner
(
g_display
,
xaClipboard
,
g_win
,
CurrentTime
);
g_selectionAcquired
|=
S_CLIPBOARD
;
}
else
TRACE
(
"No CLIPBOARD targets - ownership not acquired.
\n
"
);
return
g_selectionAcquired
;
}
BOOL
GetSelectionEvent
(
Atom
SelectionSrc
,
XEvent
*
xe
)
{
time_t
end_time
;
/* Set up a 10 second time out */
end_time
=
time
(
NULL
)
+
10
;
do
{
struct
timeval
nap
;
if
(
XCheckTypedWindowEvent
(
g_display
,
g_win
,
SelectionNotify
,
xe
))
{
if
(
xe
->
xselection
.
selection
==
SelectionSrc
)
return
TRUE
;
}
if
(
time
(
NULL
)
>
end_time
)
break
;
/* Sleep a bit to make this busy wait less brutal */
nap
.
tv_sec
=
0
;
nap
.
tv_usec
=
10
;
select
(
0
,
NULL
,
NULL
,
NULL
,
&
nap
);
}
while
(
TRUE
);
return
FALSE
;
}
/**************************************************************************
* CacheDataFormats
*
* Allocates and caches the list of data formats available from the current selection.
* This queries the selection owner for the TARGETS property and saves all
* reported property types.
*/
int
CacheDataFormats
(
Atom
SelectionSrc
,
PCACHEENTRY
*
ppCache
)
{
XEvent
xe
;
Atom
aTargets
;
Atom
atype
=
AnyPropertyType
;
int
aformat
;
unsigned
long
remain
;
unsigned
long
cSelectionTargets
=
0
;
Atom
*
targetList
=
NULL
;
Window
ownerSelection
=
0
;
if
(
!
ppCache
)
return
0
;
*
ppCache
=
NULL
;
/* Get the selection owner */
ownerSelection
=
XGetSelectionOwner
(
g_display
,
SelectionSrc
);
if
(
ownerSelection
==
None
)
return
cSelectionTargets
;
/*
* Query the selection owner for the TARGETS property
*/
aTargets
=
XInternAtom
(
g_display
,
"TARGETS"
,
False
);
TRACE
(
"Requesting TARGETS selection for '%s' (owner=%08x)...
\n
"
,
XGetAtomName
(
g_display
,
SelectionSrc
),
(
unsigned
)
ownerSelection
);
XConvertSelection
(
g_display
,
SelectionSrc
,
aTargets
,
XInternAtom
(
g_display
,
"SELECTION_DATA"
,
False
),
g_win
,
CurrentTime
);
/*
* Wait until SelectionNotify is received
*/
if
(
!
GetSelectionEvent
(
SelectionSrc
,
&
xe
))
return
0
;
/* Verify that the selection returned a valid TARGETS property */
if
(
(
xe
.
xselection
.
target
!=
aTargets
)
||
(
xe
.
xselection
.
property
==
None
)
)
{
TRACE
(
"
\t
Could not retrieve TARGETS
\n
"
);
return
cSelectionTargets
;
}
/* Read the TARGETS property contents */
if
(
XGetWindowProperty
(
g_display
,
xe
.
xselection
.
requestor
,
xe
.
xselection
.
property
,
0
,
0x3FFF
,
True
,
AnyPropertyType
/*XA_ATOM*/
,
&
atype
,
&
aformat
,
&
cSelectionTargets
,
&
remain
,
(
unsigned
char
**
)
&
targetList
)
!=
Success
)
TRACE
(
"
\t
Couldn't read TARGETS property
\n
"
);
else
{
TRACE
(
"
\t
Type %s,Format %d,nItems %ld, Remain %ld
\n
"
,
XGetAtomName
(
g_display
,
atype
),
aformat
,
cSelectionTargets
,
remain
);
/*
* The TARGETS property should have returned us a list of atoms
* corresponding to each selection target format supported.
*/
if
(
(
atype
==
XA_ATOM
||
atype
==
aTargets
)
&&
aformat
==
32
)
{
int
i
;
/* Allocate the selection cache */
*
ppCache
=
(
PCACHEENTRY
)
calloc
(
cSelectionTargets
,
sizeof
(
CACHEENTRY
));
/* Cache these formats in the selection cache */
for
(
i
=
0
;
i
<
cSelectionTargets
;
i
++
)
{
char
*
itemFmtName
=
XGetAtomName
(
g_display
,
targetList
[
i
]);
TRACE
(
"
\t
Atom# %d: '%s'
\n
"
,
i
,
itemFmtName
);
/* Populate the cache entry */
if
(
!
FillCacheEntry
(
SelectionSrc
,
targetList
[
i
],
&
((
*
ppCache
)[
i
])))
ERR
(
"Failed to fill cache entry!
\n
"
);
XFree
(
itemFmtName
);
}
}
/* Free the list of targets */
XFree
(
targetList
);
}
return
cSelectionTargets
;
}
/***********************************************************************
* FillCacheEntry
*
* Populates the specified cache entry
*/
BOOL
FillCacheEntry
(
Atom
SelectionSrc
,
Atom
target
,
PCACHEENTRY
pCacheEntry
)
{
XEvent
xe
;
Window
w
;
Atom
prop
,
reqType
;
Atom
atype
=
AnyPropertyType
;
int
aformat
;
unsigned
long
nitems
,
remain
,
itemSize
;
long
lRequestLength
;
unsigned
char
*
val
=
NULL
;
BOOL
bRet
=
FALSE
;
TRACE
(
"Requesting %s selection from %s...
\n
"
,
XGetAtomName
(
g_display
,
target
),
XGetAtomName
(
g_display
,
SelectionSrc
)
);
/* Ask the selection owner to convert the selection to the target format */
XConvertSelection
(
g_display
,
SelectionSrc
,
target
,
XInternAtom
(
g_display
,
"SELECTION_DATA"
,
False
),
g_win
,
CurrentTime
);
/* wait until SelectionNotify is received */
if
(
!
GetSelectionEvent
(
SelectionSrc
,
&
xe
))
return
bRet
;
/* Now proceed to retrieve the actual converted property from
* the SELECTION_DATA atom */
w
=
xe
.
xselection
.
requestor
;
prop
=
xe
.
xselection
.
property
;
reqType
=
xe
.
xselection
.
target
;
if
(
prop
==
None
)
{
TRACE
(
"
\t
Owner failed to convert selection!
\n
"
);
return
bRet
;
}
TRACE
(
"
\t
retrieving property %s from window %ld into %s
\n
"
,
XGetAtomName
(
g_display
,
reqType
),
(
long
)
w
,
XGetAtomName
(
g_display
,
prop
)
);
/*
* First request a zero length in order to figure out the request size.
*/
if
(
XGetWindowProperty
(
g_display
,
w
,
prop
,
0
,
0
,
False
,
AnyPropertyType
/*reqType*/
,
&
atype
,
&
aformat
,
&
nitems
,
&
itemSize
,
&
val
)
!=
Success
)
{
WARN
(
"
\t
couldn't get property size
\n
"
);
return
bRet
;
}
/* Free zero length return data if any */
if
(
val
)
{
XFree
(
val
);
val
=
NULL
;
}
TRACE
(
"
\t
retrieving %ld bytes...
\n
"
,
itemSize
*
aformat
/
8
);
lRequestLength
=
(
itemSize
*
aformat
/
8
)
/
4
+
1
;
/*
* Retrieve the actual property in the required X format.
*/
if
(
XGetWindowProperty
(
g_display
,
w
,
prop
,
0
,
lRequestLength
,
False
,
AnyPropertyType
/*reqType*/
,
&
atype
,
&
aformat
,
&
nitems
,
&
remain
,
&
val
)
!=
Success
)
{
WARN
(
"
\t
couldn't read property
\n
"
);
return
bRet
;
}
TRACE
(
"
\t
Type %s,Format %d,nitems %ld,remain %ld,value %s
\n
"
,
atype
?
XGetAtomName
(
g_display
,
atype
)
:
NULL
,
aformat
,
nitems
,
remain
,
val
);
if
(
remain
)
{
WARN
(
"
\t
Couldn't read entire property- selection may be too large! Remain=%ld
\n
"
,
remain
);
goto
END
;
}
/*
* Populate the cache entry
*/
pCacheEntry
->
target
=
target
;
pCacheEntry
->
type
=
atype
;
pCacheEntry
->
nFormat
=
aformat
;
pCacheEntry
->
nElements
=
nitems
;
if
(
atype
==
XA_PIXMAP
)
{
Pixmap
*
pPixmap
=
(
Pixmap
*
)
val
;
Pixmap
newPixmap
=
DuplicatePixmap
(
*
pPixmap
);
pPixmap
=
(
Pixmap
*
)
calloc
(
1
,
sizeof
(
Pixmap
));
*
pPixmap
=
newPixmap
;
pCacheEntry
->
pData
=
pPixmap
;
}
else
pCacheEntry
->
pData
=
val
;
END:
/* Delete the property on the window now that we are done
* This will send a PropertyNotify event to the selection owner. */
XDeleteProperty
(
g_display
,
w
,
prop
);
return
TRUE
;
}
/***********************************************************************
* LookupCacheItem
*
* Lookup a target atom in the cache and get the matching cache entry
*/
BOOL
LookupCacheItem
(
Atom
selection
,
Atom
target
,
PCACHEENTRY
*
ppCacheEntry
)
{
int
i
;
int
nCachetargets
=
0
;
PCACHEENTRY
pCache
=
NULL
;
Atom
xaClipboard
=
XInternAtom
(
g_display
,
_CLIPBOARD
,
False
);
/* Locate the cache to be used based on the selection type */
if
(
selection
==
XA_PRIMARY
)
{
pCache
=
g_pPrimaryCache
;
nCachetargets
=
g_cPrimaryTargets
;
}
else
if
(
selection
==
xaClipboard
)
{
pCache
=
g_pClipboardCache
;
nCachetargets
=
g_cClipboardTargets
;
}
if
(
!
pCache
||
!
ppCacheEntry
)
return
FALSE
;
*
ppCacheEntry
=
NULL
;
/* Look for the target item in the cache */
for
(
i
=
0
;
i
<
nCachetargets
;
i
++
)
{
if
(
pCache
[
i
].
target
==
target
)
{
*
ppCacheEntry
=
&
pCache
[
i
];
return
TRUE
;
}
}
return
FALSE
;
}
/***********************************************************************
* EmptyCache
*
* Empties the specified cache
*/
void
EmptyCache
(
PCACHEENTRY
pCache
,
int
nItems
)
{
int
i
;
if
(
!
pCache
)
return
;
/* Release all items in the cache */
for
(
i
=
0
;
i
<
nItems
;
i
++
)
{
if
(
pCache
[
i
].
target
&&
pCache
[
i
].
pData
)
{
/* If we have a Pixmap, free it first */
if
(
pCache
[
i
].
target
==
XA_PIXMAP
||
pCache
[
i
].
target
==
XA_BITMAP
)
{
Pixmap
*
pPixmap
=
(
Pixmap
*
)
pCache
[
i
].
pData
;
TRACE
(
"Freeing %s (handle=%ld)...
\n
"
,
XGetAtomName
(
g_display
,
pCache
[
i
].
target
),
*
pPixmap
);
XFreePixmap
(
g_display
,
*
pPixmap
);
/* Free the cached data item (allocated by us) */
free
(
pCache
[
i
].
pData
);
}
else
{
TRACE
(
"Freeing %s (%p)...
\n
"
,
XGetAtomName
(
g_display
,
pCache
[
i
].
target
),
pCache
[
i
].
pData
);
/* Free the cached data item (allocated by X) */
XFree
(
pCache
[
i
].
pData
);
}
}
}
/* Destroy the cache */
free
(
pCache
);
}
/***********************************************************************
* EVENT_ProcessEvent
*
* Process an X event.
*/
void
EVENT_ProcessEvent
(
XEvent
*
event
)
{
/*
static const char * const event_names[] =
{
"", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
"MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
"KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
"CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
"ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
"ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
"SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
"ClientMessage", "MappingNotify"
};
TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
*/
switch
(
event
->
type
)
{
case
Expose
:
/* don't draw the window */
if
(
event
->
xexpose
.
count
!=
0
)
break
;
/* Output something */
TextOut
(
g_win
,
g_gc
,
"Click here to terminate"
);
break
;
case
ConfigureNotify
:
break
;
case
ButtonPress
:
/* fall into KeyPress (no break) */
case
KeyPress
:
TerminateServer
(
1
);
break
;
case
SelectionRequest
:
EVENT_SelectionRequest
(
(
XSelectionRequestEvent
*
)
event
,
FALSE
);
break
;
case
SelectionClear
:
EVENT_SelectionClear
(
(
XSelectionClearEvent
*
)
event
);
break
;
case
PropertyNotify
:
#if 0
EVENT_PropertyNotify( (XPropertyEvent *)event );
#endif
break
;
default:
/* ignore all other events */
break
;
}
/* end switch */
}
/***********************************************************************
* EVENT_SelectionRequest_MULTIPLE
* Service a MULTIPLE selection request event
* rprop contains a list of (target,property) atom pairs.
* The first atom names a target and the second names a property.
* The effect is as if we have received a sequence of SelectionRequest events
* (one for each atom pair) except that:
* 1. We reply with a SelectionNotify only when all the requested conversions
* have been performed.
* 2. If we fail to convert the target named by an atom in the MULTIPLE property,
* we replace the atom in the property by None.
*/
Atom
EVENT_SelectionRequest_MULTIPLE
(
XSelectionRequestEvent
*
pevent
)
{
Atom
rprop
;
Atom
atype
=
AnyPropertyType
;
int
aformat
;
unsigned
long
remain
;
Atom
*
targetPropList
=
NULL
;
unsigned
long
cTargetPropList
=
0
;
/* Atom xAtomPair = XInternAtom(g_display, "ATOM_PAIR", False); */
/* If the specified property is None the requestor is an obsolete client.
* We support these by using the specified target atom as the reply property.
*/
rprop
=
pevent
->
property
;
if
(
rprop
==
None
)
rprop
=
pevent
->
target
;
if
(
!
rprop
)
goto
END
;
/* Read the MULTIPLE property contents. This should contain a list of
* (target,property) atom pairs.
*/
if
(
XGetWindowProperty
(
g_display
,
pevent
->
requestor
,
rprop
,
0
,
0x3FFF
,
False
,
AnyPropertyType
,
&
atype
,
&
aformat
,
&
cTargetPropList
,
&
remain
,
(
unsigned
char
**
)
&
targetPropList
)
!=
Success
)
TRACE
(
"
\t
Couldn't read MULTIPLE property
\n
"
);
else
{
TRACE
(
"
\t
Type %s,Format %d,nItems %ld, Remain %ld
\n
"
,
XGetAtomName
(
g_display
,
atype
),
aformat
,
cTargetPropList
,
remain
);
/*
* Make sure we got what we expect.
* NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
* in a MULTIPLE selection request should be of type ATOM_PAIR.
* However some X apps(such as XPaint) are not compliant with this and return
* a user defined atom in atype when XGetWindowProperty is called.
* The data *is* an atom pair but is not denoted as such.
*/
if
(
aformat
==
32
/* atype == xAtomPair */
)
{
int
i
;
/* Iterate through the ATOM_PAIR list and execute a SelectionRequest
* for each (target,property) pair */
for
(
i
=
0
;
i
<
cTargetPropList
;
i
+=
2
)
{
char
*
targetName
=
XGetAtomName
(
g_display
,
targetPropList
[
i
]);
char
*
propName
=
XGetAtomName
(
g_display
,
targetPropList
[
i
+
1
]);
XSelectionRequestEvent
event
;
TRACE
(
"MULTIPLE(%d): Target='%s' Prop='%s'
\n
"
,
i
/
2
,
targetName
,
propName
);
XFree
(
targetName
);
XFree
(
propName
);
/* We must have a non "None" property to service a MULTIPLE target atom */
if
(
!
targetPropList
[
i
+
1
]
)
{
TRACE
(
"
\t
MULTIPLE(%d): Skipping target with empty property!
\n
"
,
i
);
continue
;
}
/* Set up an XSelectionRequestEvent for this (target,property) pair */
memcpy
(
&
event
,
pevent
,
sizeof
(
XSelectionRequestEvent
)
);
event
.
target
=
targetPropList
[
i
];
event
.
property
=
targetPropList
[
i
+
1
];
/* Fire a SelectionRequest, informing the handler that we are processing
* a MULTIPLE selection request event.
*/
EVENT_SelectionRequest
(
&
event
,
TRUE
);
}
}
/* Free the list of targets/properties */
XFree
(
targetPropList
);
}
END:
return
rprop
;
}
/***********************************************************************
* EVENT_SelectionRequest
* Process an event selection request event.
* The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
* recursively while servicing a "MULTIPLE" selection target.
*
*/
void
EVENT_SelectionRequest
(
XSelectionRequestEvent
*
event
,
BOOL
bIsMultiple
)
{
XSelectionEvent
result
;
Atom
rprop
=
None
;
Window
request
=
event
->
requestor
;
Atom
xaMultiple
=
XInternAtom
(
g_display
,
"MULTIPLE"
,
False
);
PCACHEENTRY
pCacheEntry
=
NULL
;
void
*
pData
=
NULL
;
Pixmap
pixmap
;
/* If the specified property is None the requestor is an obsolete client.
* We support these by using the specified target atom as the reply property.
*/
rprop
=
event
->
property
;
if
(
rprop
==
None
)
rprop
=
event
->
target
;
TRACE
(
"Request for %s in selection %s
\n
"
,
XGetAtomName
(
g_display
,
event
->
target
),
XGetAtomName
(
g_display
,
event
->
selection
));
/* Handle MULTIPLE requests - rprop contains a list of (target, property) atom pairs */
if
(
event
->
target
==
xaMultiple
)
{
/* MULTIPLE selection request - will call us back recursively */
rprop
=
EVENT_SelectionRequest_MULTIPLE
(
event
);
goto
END
;
}
/* Lookup the requested target property in the cache */
if
(
!
LookupCacheItem
(
event
->
selection
,
event
->
target
,
&
pCacheEntry
)
)
{
TRACE
(
"Item not available in cache!
\n
"
);
goto
END
;
}
/* Update the X property */
TRACE
(
"
\t
Updating property %s...
\n
"
,
XGetAtomName
(
g_display
,
rprop
));
/* If we have a request for a pixmap, return a duplicate */
if
(
event
->
target
==
XA_PIXMAP
||
event
->
target
==
XA_BITMAP
)
{
Pixmap
*
pPixmap
=
(
Pixmap
*
)
pCacheEntry
->
pData
;
pixmap
=
DuplicatePixmap
(
*
pPixmap
);
pData
=
&
pixmap
;
}
else
pData
=
pCacheEntry
->
pData
;
XChangeProperty
(
g_display
,
request
,
rprop
,
pCacheEntry
->
type
,
pCacheEntry
->
nFormat
,
PropModeReplace
,
(
unsigned
char
*
)
pData
,
pCacheEntry
->
nElements
);
END:
if
(
rprop
==
None
)
TRACE
(
"
\t
Request ignored
\n
"
);
/* reply to sender
* SelectionNotify should be sent only at the end of a MULTIPLE request
*/
if
(
!
bIsMultiple
)
{
result
.
type
=
SelectionNotify
;
result
.
display
=
g_display
;
result
.
requestor
=
request
;
result
.
selection
=
event
->
selection
;
result
.
property
=
rprop
;
result
.
target
=
event
->
target
;
result
.
time
=
event
->
time
;
TRACE
(
"Sending SelectionNotify event...
\n
"
);
XSendEvent
(
g_display
,
event
->
requestor
,
False
,
NoEventMask
,(
XEvent
*
)
&
result
);
}
}
/***********************************************************************
* EVENT_SelectionClear
* We receive this event when another client grabs the X selection.
* If we lost both PRIMARY and CLIPBOARD we must terminate.
*/
void
EVENT_SelectionClear
(
XSelectionClearEvent
*
event
)
{
Atom
xaClipboard
=
XInternAtom
(
g_display
,
_CLIPBOARD
,
False
);
TRACE
(
"()
\n
"
);
/* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
* dictate that *all* selections should be cleared on loss of a selection,
* we must give up all the selections we own.
*/
if
(
g_clearAllSelections
||
(
event
->
selection
==
xaClipboard
)
)
{
TRACE
(
"Lost CLIPBOARD (+PRIMARY) selection
\n
"
);
/* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
if
(
(
event
->
selection
==
xaClipboard
)
&&
(
g_selectionAcquired
&
S_PRIMARY
)
)
{
XSetSelectionOwner
(
g_display
,
XA_PRIMARY
,
None
,
CurrentTime
);
}
/* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
if
(
(
event
->
selection
==
XA_PRIMARY
)
&&
(
g_selectionAcquired
&
S_CLIPBOARD
)
)
{
XSetSelectionOwner
(
g_display
,
xaClipboard
,
None
,
CurrentTime
);
}
g_selectionAcquired
=
S_NOSELECTION
;
/* Clear the selection masks */
}
else
if
(
event
->
selection
==
XA_PRIMARY
)
{
TRACE
(
"Lost PRIMARY selection...
\n
"
);
g_selectionAcquired
&=
~
S_PRIMARY
;
/* Clear the PRIMARY flag */
}
/* Once we lose all our selections we have nothing more to do */
if
(
g_selectionAcquired
==
S_NOSELECTION
)
TerminateServer
(
1
);
}
/***********************************************************************
* EVENT_PropertyNotify
* We use this to release resources like Pixmaps when a selection
* client no longer needs them.
*/
void
EVENT_PropertyNotify
(
XPropertyEvent
*
event
)
{
TRACE
(
"()
\n
"
);
/* Check if we have any resources to free */
switch
(
event
->
state
)
{
case
PropertyDelete
:
{
TRACE
(
"
\t
PropertyDelete for atom %s on window %ld
\n
"
,
XGetAtomName
(
event
->
display
,
event
->
atom
),
(
long
)
event
->
window
);
/* FreeResources( event->atom ); */
break
;
}
case
PropertyNewValue
:
{
TRACE
(
"
\t
PropertyNewValue for atom %s on window %ld
\n\n
"
,
XGetAtomName
(
event
->
display
,
event
->
atom
),
(
long
)
event
->
window
);
break
;
}
default:
break
;
}
}
/***********************************************************************
* DuplicatePixmap
*/
Pixmap
DuplicatePixmap
(
Pixmap
pixmap
)
{
Pixmap
newPixmap
;
XImage
*
xi
;
Window
root
;
int
x
,
y
;
/* Unused */
unsigned
border_width
;
/* Unused */
unsigned
int
depth
,
width
,
height
;
TRACE
(
"
\t
() Pixmap=%ld
\n
"
,
(
long
)
pixmap
);
/* Get the Pixmap dimensions and bit depth */
if
(
0
==
XGetGeometry
(
g_display
,
pixmap
,
&
root
,
&
x
,
&
y
,
&
width
,
&
height
,
&
border_width
,
&
depth
)
)
return
0
;
TRACE
(
"
\t
Pixmap properties: width=%d, height=%d, depth=%d
\n
"
,
width
,
height
,
depth
);
newPixmap
=
XCreatePixmap
(
g_display
,
g_win
,
width
,
height
,
depth
);
xi
=
XGetImage
(
g_display
,
pixmap
,
0
,
0
,
width
,
height
,
AllPlanes
,
XYPixmap
);
XPutImage
(
g_display
,
newPixmap
,
g_gc
,
xi
,
0
,
0
,
0
,
0
,
width
,
height
);
XDestroyImage
(
xi
);
TRACE
(
"
\t
() New Pixmap=%ld
\n
"
,
(
long
)
newPixmap
);
return
newPixmap
;
}
/***********************************************************************
* getGC
* Get a GC to use for drawing
*/
void
getGC
(
Window
win
,
GC
*
gc
)
{
unsigned
long
valuemask
=
0
;
/* ignore XGCvalues and use defaults */
XGCValues
values
;
unsigned
int
line_width
=
6
;
int
line_style
=
LineOnOffDash
;
int
cap_style
=
CapRound
;
int
join_style
=
JoinRound
;
int
dash_offset
=
0
;
static
char
dash_list
[]
=
{
12
,
24
};
int
list_length
=
2
;
/* Create default Graphics Context */
*
gc
=
XCreateGC
(
g_display
,
win
,
valuemask
,
&
values
);
/* specify black foreground since default window background is
* white and default foreground is undefined. */
XSetForeground
(
g_display
,
*
gc
,
BlackPixel
(
g_display
,
screen_num
));
/* set line attributes */
XSetLineAttributes
(
g_display
,
*
gc
,
line_width
,
line_style
,
cap_style
,
join_style
);
/* set dashes */
XSetDashes
(
g_display
,
*
gc
,
dash_offset
,
dash_list
,
list_length
);
}
/***********************************************************************
* TextOut
*/
void
TextOut
(
Window
win
,
GC
gc
,
char
*
pStr
)
{
int
y_offset
,
x_offset
;
y_offset
=
10
;
x_offset
=
2
;
/* output text, centered on each line */
XDrawString
(
g_display
,
win
,
gc
,
x_offset
,
y_offset
,
pStr
,
strlen
(
pStr
));
}
documentation/PACKAGING
View file @
9fff718a
...
...
@@ -178,8 +178,6 @@ WINE COMPONENTS
- winebuild : Winebuild is a tool used for building Winelib applications
(and by Wine itself) to allow a developer to compile a .spec file
into a .spec.c file.
- wineclipserv : The Wine Clipboard Server is a standalone XLib application
whose purpose is to manage the X selection when Wine exits.
- wineconsole : Render the output of CUI programs.
- winedbg : A application making use of the debugging API to allow
debugging of Wine or Winelib applications as well as Wine itself
...
...
@@ -462,9 +460,6 @@ Example (split this into %build and %install section for rpm:
install -d $BR/usr/X11R6/lib/wine
mv $BR/usr/X11R6/lib/lib* $BR/usr/X11R6/lib/wine/
# the clipboard server is started on demand.
install -m 755 dlls/x11drv/wineclipsrv $BR/usr/X11R6/bin/
# The Wine server is needed.
install -m 755 server/wineserver $BR/usr/X11R6/bin/
...
...
@@ -477,9 +472,9 @@ separate library directory should be used.
You will need to package the files:
$prefix/bin/wine, $prefix/
bin/dosmod, $prefix/
lib/wine/*
$prefix/bin/wine, $prefix/lib/wine/*
$prefix/man/man1/wine.1, $prefix/include/wine/*,
$prefix/bin/wineserver
, $prefix/bin/wineclipsrv
$prefix/bin/wineserver
%config /etc/wine/*
%doc ... choose from the toplevel directory and documentation/
...
...
documentation/samples/config
View file @
9fff718a
...
...
@@ -159,7 +159,6 @@ WINE REGISTRY Version 2
[Clipboard]
"ClearAllSelections" = "0"
"PersistentSelection" = "1"
"UsePrimary" = "0"
; List of all directories directly contain .AFM files
...
...
documentation/wine.man.in
View file @
9fff718a
...
...
@@ -233,11 +233,6 @@ The
.B wine
debugger
.TP
.I @bindir@/wineclipsrv
The
.B wine
clipboard server
.TP
.I @dlldir@
Directory containing
.B wine's
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment