Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
56ab55d3
Commit
56ab55d3
authored
Oct 24, 1999
by
Francis Beaudet
Committed by
Alexandre Julliard
Oct 24, 1999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Enabled the persistent clipboard server.
parent
7bf36ad3
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
365 additions
and
130 deletions
+365
-130
clipboard.c
dlls/ole32/clipboard.c
+17
-14
clipboard.c
windows/clipboard.c
+5
-3
user.c
windows/user.c
+0
-5
Makefile.in
windows/x11drv/Makefile.in
+1
-3
clipboard.c
windows/x11drv/clipboard.c
+172
-63
wineclipsrv.c
windows/x11drv/wineclipsrv.c
+166
-42
wine.ini
wine.ini
+4
-0
No files found.
dlls/ole32/clipboard.c
View file @
56ab55d3
...
...
@@ -146,7 +146,7 @@ static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
static
HWND
OLEClipbrd_CreateWindow
();
static
void
OLEClipbrd_DestroyWindow
(
HWND
hwnd
);
LRESULT
CALLBACK
OLEClipbrd_WndProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
static
HRESULT
OLEClipbrd_RenderFormat
(
LPFORMATETC
pFormatetc
);
static
HRESULT
OLEClipbrd_RenderFormat
(
IDataObject
*
pIDataObject
,
LPFORMATETC
pFormatetc
);
static
HGLOBAL
OLEClipbrd_GlobalDupMem
(
HGLOBAL
hGlobalSrc
);
/*
...
...
@@ -473,6 +473,7 @@ HRESULT WINAPI OleFlushClipboard()
FORMATETC
rgelt
;
HRESULT
hr
=
S_OK
;
BOOL
bClipboardOpen
=
FALSE
;
IDataObject
*
pIDataObjectSrc
=
NULL
;
TRACE
(
"()
\n
"
);
...
...
@@ -488,6 +489,13 @@ HRESULT WINAPI OleFlushClipboard()
return
S_OK
;
/*
* Addref and save the source data object we are holding on to temporarily,
* since it will be released when we empty the clipboard.
*/
pIDataObjectSrc
=
theOleClipboard
->
pIDataObjectSrc
;
IDataObject_AddRef
(
pIDataObjectSrc
);
/*
* Open the Windows clipboard
*/
if
(
!
(
bClipboardOpen
=
OpenClipboard
(
theOleClipboard
->
hWndClipboard
))
)
...
...
@@ -503,7 +511,7 @@ HRESULT WINAPI OleFlushClipboard()
* Render all HGLOBAL formats supported by the source into
* the windows clipboard.
*/
if
(
FAILED
(
hr
=
IDataObject_EnumFormatEtc
(
(
IDataObject
*
)
&
(
theOleClipboard
->
lpvtbl1
)
,
if
(
FAILED
(
hr
=
IDataObject_EnumFormatEtc
(
pIDataObjectSrc
,
DATADIR_GET
,
&
penumFormatetc
)
))
{
...
...
@@ -522,7 +530,7 @@ HRESULT WINAPI OleFlushClipboard()
/*
* Render the clipboard data
*/
if
(
FAILED
(
OLEClipbrd_RenderFormat
(
&
rgelt
))
)
if
(
FAILED
(
OLEClipbrd_RenderFormat
(
pIDataObjectSrc
,
&
rgelt
))
)
continue
;
}
}
...
...
@@ -530,13 +538,9 @@ HRESULT WINAPI OleFlushClipboard()
IEnumFORMATETC_Release
(
penumFormatetc
);
/*
* Release the data object we are holding on to
* Release the
source
data object we are holding on to
*/
if
(
theOleClipboard
->
pIDataObjectSrc
)
{
IDataObject_Release
(
theOleClipboard
->
pIDataObjectSrc
);
theOleClipboard
->
pIDataObjectSrc
=
NULL
;
}
IDataObject_Release
(
pIDataObjectSrc
);
CLEANUP:
...
...
@@ -795,7 +799,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
* Render the clipboard data.
* (We must have a source data object or we wouldn't be in this WndProc)
*/
OLEClipbrd_RenderFormat
(
&
rgelt
);
OLEClipbrd_RenderFormat
(
(
IDataObject
*
)
&
(
theOleClipboard
->
lpvtbl1
),
&
rgelt
);
break
;
}
...
...
@@ -835,7 +839,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
/*
* Render the clipboard data.
*/
if
(
FAILED
(
OLEClipbrd_RenderFormat
(
&
rgelt
))
)
if
(
FAILED
(
OLEClipbrd_RenderFormat
(
(
IDataObject
*
)
&
(
theOleClipboard
->
lpvtbl1
),
&
rgelt
))
)
continue
;
TRACE
(
"(): WM_RENDERALLFORMATS(cfFormat=%d)
\n
"
,
rgelt
.
cfFormat
);
...
...
@@ -891,14 +895,13 @@ LRESULT CALLBACK OLEClipbrd_WndProc
* source data object.
* Note: This function assumes it is passed an HGLOBAL format to render.
*/
static
HRESULT
OLEClipbrd_RenderFormat
(
LPFORMATETC
pFormatetc
)
static
HRESULT
OLEClipbrd_RenderFormat
(
IDataObject
*
pIDataObject
,
LPFORMATETC
pFormatetc
)
{
STGMEDIUM
medium
;
HGLOBAL
hDup
;
HRESULT
hr
=
S_OK
;
if
(
FAILED
(
hr
=
IDataObject_GetData
((
IDataObject
*
)
&
(
theOleClipboard
->
lpvtbl1
),
pFormatetc
,
&
medium
))
)
if
(
FAILED
(
hr
=
IDataObject_GetData
(
pIDataObject
,
pFormatetc
,
&
medium
))
)
{
WARN
(
"() : IDataObject_GetData failed to render clipboard data! (%lx)
\n
"
,
hr
);
return
hr
;
...
...
windows/clipboard.c
View file @
56ab55d3
...
...
@@ -488,7 +488,7 @@ static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
TRACE
(
"
\t
converting from '%s' to '%s', %i chars
\n
"
,
lpSource
->
Name
,
lpTarget
->
Name
,
size
);
lpTarget
->
hData32
=
GlobalAlloc
(
GMEM_ZEROINIT
,
size
);
lpTarget
->
hData32
=
GlobalAlloc
(
GMEM_ZEROINIT
|
GMEM_MOVEABLE
|
GMEM_DDESHARE
,
size
);
lpstrT
=
(
LPSTR
)
GlobalLock
(
lpTarget
->
hData32
);
if
(
lpstrT
)
...
...
@@ -791,7 +791,8 @@ HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
}
/* Convert between 32 -> 16 bit data, if necessary */
if
(
lpRender
->
hData32
&&
!
lpRender
->
hData16
)
if
(
lpRender
->
hData32
&&
!
lpRender
->
hData16
&&
CLIPBOARD_IsMemoryObject
(
wFormat
)
)
{
int
size
;
if
(
lpRender
->
wFormatID
==
CF_METAFILEPICT
)
...
...
@@ -857,7 +858,8 @@ HANDLE WINAPI GetClipboardData( UINT wFormat )
}
/* Convert between 16 -> 32 bit data, if necessary */
if
(
lpRender
->
hData16
&&
!
lpRender
->
hData32
)
if
(
lpRender
->
hData16
&&
!
lpRender
->
hData32
&&
CLIPBOARD_IsMemoryObject
(
wFormat
)
)
{
int
size
;
if
(
lpRender
->
wFormatID
==
CF_METAFILEPICT
)
...
...
windows/user.c
View file @
56ab55d3
...
...
@@ -171,11 +171,6 @@ static void USER_AppExit( HINSTANCE16 hInstance )
* but does nothing);
*/
/* TODO: Start up persistant WINE X clipboard server process which will
* take ownership of the X selection and continue to service selection
* requests from other apps.
*/
/* ModuleUnload() in "Internals" */
hInstance
=
GetExePtr
(
hInstance
);
...
...
windows/x11drv/Makefile.in
View file @
56ab55d3
DEFS
=
@DLLFLAGS@
-D__WINE__
DEFS
=
@DLLFLAGS@
-D__WINE__
-DBINDIR
=
"
\"
$(bindir)
\"
"
TOPSRCDIR
=
@top_srcdir@
TOPOBJDIR
=
../..
SRCDIR
=
@srcdir@
...
...
@@ -23,8 +23,6 @@ all: $(MODULE).o $(PROGRAMS)
wineclipsrv
:
wineclipsrv.c
$(CC)
$(ALLCFLAGS)
-o
wineclipsrv
$(SRCDIR)
/wineclipsrv.c
$(X_LIBS)
$(XLIB)
$(LIBS)
all
:
$(MODULE).o
@MAKE_RULES@
### Dependencies:
windows/x11drv/clipboard.c
View file @
56ab55d3
...
...
@@ -49,13 +49,15 @@
#ifndef X_DISPLAY_MISSING
#include <errno.h>
#include <X11/Xatom.h>
#include <string.h>
#include <unistd.h>
#include "ts_xlib.h"
#include "wine/winuser16.h"
#include "clipboard.h"
#include "debugtools.h"
#include "message.h"
#include "win.h"
#include "windef.h"
...
...
@@ -63,6 +65,8 @@
#include "bitmap.h"
#include "commctrl.h"
#include "heap.h"
#include "options.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL
(
clipboard
)
...
...
@@ -76,13 +80,14 @@ DEFAULT_DEBUG_CHANNEL(clipboard)
static
char
_CLIPBOARD
[]
=
"CLIPBOARD"
;
/* CLIPBOARD atom name */
static
char
FMT_PREFIX
[]
=
"<WCF>"
;
/* Prefix for windows specific formats */
static
int
selectionAcquired
=
0
;
/* Contains the current selection masks */
static
int
selectionAcquired
=
0
;
/* Contains the current selection masks */
static
Window
selectionWindow
=
None
;
/* The top level X window which owns the selection */
static
Window
selectionPrevWindow
=
None
;
/* The last X window that owned the selection */
static
Window
PrimarySelectionOwner
=
None
;
/* The window which owns the primary selection */
static
Window
ClipboardSelectionOwner
=
None
;
/* The window which owns the clipboard selection */
static
unsigned
long
cSelectionTargets
=
0
;
/* Number of target formats reported by TARGETS selection */
static
Atom
selectionCacheSrc
=
XA_PRIMARY
;
/* The selection source from which the clipboard cache was filled */
static
HANDLE
selectionClearEvent
=
NULL
;
/* Synchronization object used to block until server is started */
/*
* Dynamic pointer arrays to manage destruction of Pixmap resources
...
...
@@ -206,6 +211,106 @@ BOOL X11DRV_CLIPBOARD_IsNativeProperty(Atom prop)
/**************************************************************************
* X11DRV_CLIPBOARD_LaunchServer
* Launches the clipboard server. This is called from X11DRV_CLIPBOARD_ResetOwner
* when the selection can no longer be recyled to another top level window.
* In order to make the selection persist after Wine shuts down a server
* process is launched which services subsequent selection requests.
*/
BOOL
X11DRV_CLIPBOARD_LaunchServer
()
{
int
iWndsLocks
;
/* If persistant selection has been disabled in the .winerc Clipboard section,
* don't launch the server
*/
if
(
!
PROFILE_GetWineIniInt
(
"Clipboard"
,
"PersistentSelection"
,
1
)
)
return
FALSE
;
/* Start up persistant WINE X clipboard server process which will
* take ownership of the X selection and continue to service selection
* requests from other apps.
*/
selectionWindow
=
selectionPrevWindow
;
if
(
!
fork
()
)
{
/* NOTE: This code only executes in the context of the child process
* Do note make any Wine specific calls here.
*/
int
dbgClasses
=
0
;
char
selMask
[
8
],
dbgClassMask
[
8
],
clearSelection
[
8
];
sprintf
(
selMask
,
"%d"
,
selectionAcquired
);
/* Build the debug class mask to pass to the server, by inheriting
* the settings for the clipboard debug channel.
*/
dbgClasses
|=
__GET_DEBUGGING
(
__DBCL_FIXME
,
dbch_clipboard
)
?
1
:
0
;
dbgClasses
|=
__GET_DEBUGGING
(
__DBCL_ERR
,
dbch_clipboard
)
?
2
:
0
;
dbgClasses
|=
__GET_DEBUGGING
(
__DBCL_WARN
,
dbch_clipboard
)
?
4
:
0
;
dbgClasses
|=
__GET_DEBUGGING
(
__DBCL_TRACE
,
dbch_clipboard
)
?
8
:
0
;
sprintf
(
dbgClassMask
,
"%d"
,
dbgClasses
);
/* Get the clear selection preference */
sprintf
(
clearSelection
,
"%d"
,
PROFILE_GetWineIniInt
(
"Clipboard"
,
"ClearAllSelections"
,
0
));
/* Exec the clipboard server passing it the selection and debug class masks */
execl
(
BINDIR
"/wineclipsvr"
,
"wineclipsvr"
,
selMask
,
dbgClassMask
,
clearSelection
,
NULL
);
execlp
(
"wineclipsvr"
,
"wineclipsvr"
,
selMask
,
dbgClassMask
,
clearSelection
,
NULL
);
execl
(
"./windows/x11drv/wineclipsvr"
,
"wineclipsvr"
,
selMask
,
dbgClassMask
,
clearSelection
,
NULL
);
/* Exec Failed! */
perror
(
"Could not start Wine clipboard server"
);
exit
(
1
);
/* Exit the child process */
}
/* Wait until the clipboard server acquires the selection.
* We must release the windows lock to enable Wine to process
* selection messages in response to the servers requests.
*/
iWndsLocks
=
WIN_SuspendWndsLock
();
/* We must wait until the server finishes acquiring the selection,
* before proceeding, otherwise the window which owns the selection
* will be destroyed prematurely!
* Create a non-signalled, auto-reset event which will be set by
* X11DRV_CLIPBOARD_ReleaseSelection, and wait until this gets
* signalled before proceeding.
*/
if
(
!
(
selectionClearEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
))
)
ERR
(
"Could not create wait object. Clipboard server won't start!
\n
"
);
else
{
/* Make the event object's handle global */
selectionClearEvent
=
ConvertToGlobalHandle
(
selectionClearEvent
);
/* Wait until we lose the selection, timing out after a minute */
TRACE
(
"Waiting for clipboard server to acquire selection
\n
"
);
if
(
WaitForSingleObject
(
selectionClearEvent
,
60000
)
!=
WAIT_OBJECT_0
)
TRACE
(
"Server could not acquire selection, or a time out occured!
\n
"
);
else
TRACE
(
"Server successfully acquired selection
\n
"
);
/* Release the event */
CloseHandle
(
selectionClearEvent
);
selectionClearEvent
=
NULL
;
}
WIN_RestoreWndsLock
(
iWndsLocks
);
return
TRUE
;
}
/**************************************************************************
* X11DRV_CLIPBOARD_CacheDataFormats
*
* Caches the list of data formats available from the current selection.
...
...
@@ -567,14 +672,14 @@ END:
* Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
* to a SelectionClear event.
* This can occur in response to another client grabbing the X selection.
* If the XA_CLIPBOARD selection is lost we relinquish XA_PRIMARY as well.
* If the XA_CLIPBOARD selection is lost
,
we relinquish XA_PRIMARY as well.
*/
void
X11DRV_CLIPBOARD_ReleaseSelection
(
Atom
selType
,
Window
w
,
HWND
hwnd
)
{
Atom
xaClipboard
=
TSXInternAtom
(
display
,
"CLIPBOARD"
,
False
);
int
clearAllSelections
=
PROFILE_GetWineIniInt
(
"Clipboard"
,
"ClearAllSelections"
,
0
);
/* w is the window that lost selection,
*
/* w is the window that lost the selection
* selectionPrevWindow is nonzero if CheckSelection() was called.
*/
...
...
@@ -585,12 +690,15 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
{
if
(
w
==
selectionWindow
||
selectionPrevWindow
==
None
)
{
/* alright, we really lost it */
if
(
selType
==
xaClipboard
)
/* completely give up the selection */
/* 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
(
clearAllSelections
||
(
selType
==
xaClipboard
)
)
{
TRACE
(
"Lost CLIPBOARD selection
\n
"
);
/* completely give up the selection */
TRACE
(
"Lost CLIPBOARD (+PRIMARY) selection
\n
"
);
/* We are completely giving up the selection.
* Make sure we can open the windows clipboard first. */
...
...
@@ -607,24 +715,23 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
return
;
}
selectionPrevWindow
=
selectionWindow
;
selectionWindow
=
None
;
PrimarySelectionOwner
=
ClipboardSelectionOwner
=
0
;
/* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
if
(
(
selType
==
xaClipboard
)
&&
(
selectionAcquired
&
S_PRIMARY
)
)
{
XSetSelectionOwner
(
display
,
XA_PRIMARY
,
None
,
CurrentTime
);
}
/* Voluntarily give up the PRIMARY selection if we still own it */
if
(
selectionAcquired
&
S_PRIMARY
)
/* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
if
(
(
selType
==
XA_PRIMARY
)
&&
(
selectionAcquired
&
S_CLIPBOARD
)
)
{
XEvent
xe
;
TRACE
(
"Releasing XA_PRIMARY selection
\n
"
);
TSXSetSelectionOwner
(
display
,
XA_PRIMARY
,
None
,
CurrentTime
);
/* Wait until SelectionClear is processed */
if
(
selectionPrevWindow
)
while
(
!
XCheckTypedWindowEvent
(
display
,
selectionPrevWindow
,
SelectionClear
,
&
xe
)
);
XSetSelectionOwner
(
display
,
xaClipboard
,
None
,
CurrentTime
);
}
selectionWindow
=
None
;
PrimarySelectionOwner
=
ClipboardSelectionOwner
=
0
;
/* Empty the windows clipboard.
* We should pretend that we still own the selection BEFORE calling
* EmptyClipboard() since otherwise this has the side effect of
...
...
@@ -633,12 +740,13 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
*/
selectionAcquired
=
(
S_PRIMARY
|
S_CLIPBOARD
);
EmptyClipboard
();
selectionAcquired
=
S_NOSELECTION
;
CloseClipboard
();
/* Give up ownership of the windows clipboard */
CLIPBOARD_ReleaseOwner
();
/* Reset the selection flags now that we are done */
selectionAcquired
=
S_NOSELECTION
;
}
else
if
(
selType
==
XA_PRIMARY
)
/* Give up only PRIMARY selection */
{
...
...
@@ -664,6 +772,13 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
}
}
/* Signal to a selectionClearEvent listener if the selection is completely lost */
if
(
selectionClearEvent
&&
!
selectionAcquired
)
{
TRACE
(
"Lost all selections, signalling to selectionClearEvent listener
\n
"
);
SetEvent
(
selectionClearEvent
);
}
selectionPrevWindow
=
None
;
}
...
...
@@ -996,21 +1111,6 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
TRACE
(
"clipboard owner = %04x, selection window = %08x
\n
"
,
hWndClipOwner
,
(
unsigned
)
selectionWindow
);
#if(0)
/* Check if all formats are already in the clipboard cache */
if
(
!
CLIPBOARD_IsCacheRendered
()
)
{
SendMessage16
(
hWndClipOwner
,
WM_RENDERALLFORMATS
,
0
,
0L
);
/* check if all formats were rendered */
if
(
!
CLIPBOARD_IsCacheRendered
()
)
{
ERR
(
"
\t
Could not render all formats
\n
"
);
CLIPBOARD_ReleaseOwner
();
}
}
#endif
/* now try to salvage current selection from being destroyed by X */
TRACE
(
"
\t
checking %08x
\n
"
,
(
unsigned
)
XWnd
);
...
...
@@ -1041,7 +1141,10 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
TSXSetSelectionOwner
(
display
,
XA_PRIMARY
,
selectionWindow
,
CurrentTime
);
TSXSetSelectionOwner
(
display
,
xaClipboard
,
selectionWindow
,
CurrentTime
);
/* Restore the selection masks */
selectionAcquired
=
saveSelectionState
;
/* Lose the selection if something went wrong */
if
(
(
(
saveSelectionState
&
S_PRIMARY
)
&&
(
TSXGetSelectionOwner
(
display
,
XA_PRIMARY
)
!=
selectionWindow
)
)
...
...
@@ -1053,7 +1156,6 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
else
{
/* Update selection state */
selectionAcquired
=
saveSelectionState
;
if
(
saveSelectionState
&
S_PRIMARY
)
PrimarySelectionOwner
=
selectionWindow
;
...
...
@@ -1069,26 +1171,33 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
END:
if
(
bLostSelection
)
{
/* Empty the windows clipboard.
* We should pretend that we still own the selection BEFORE calling
* EmptyClipboard() since otherwise this has the side effect of
* triggering X11DRV_CLIPBOARD_Acquire() and causing the X selection
* to be re-acquired by us!
*/
/* Launch the clipboard server if the selection can no longer be recyled
* to another top level window. */
if
(
!
X11DRV_CLIPBOARD_LaunchServer
()
)
{
/* Empty the windows clipboard if the server was not launched.
* We should pretend that we still own the selection BEFORE calling
* EmptyClipboard() since otherwise this has the side effect of
* triggering X11DRV_CLIPBOARD_Acquire() and causing the X selection
* to be re-acquired by us!
*/
TRACE
(
"
\t
Lost the selection! Emptying the clipboard...
\n
"
);
OpenClipboard
(
NULL
);
selectionAcquired
=
(
S_PRIMARY
|
S_CLIPBOARD
);
EmptyClipboard
();
CloseClipboard
();
/* Give up ownership of the windows clipboard */
CLIPBOARD_ReleaseOwner
();
}
TRACE
(
"
\t
Lost the selection! Emptying the clipboard...
\n
"
);
OpenClipboard
(
NULL
);
selectionAcquired
=
(
S_PRIMARY
|
S_CLIPBOARD
);
EmptyClipboard
();
selectionAcquired
=
S_NOSELECTION
;
CloseClipboard
();
/* Give up ownership of the windows clipboard */
CLIPBOARD_ReleaseOwner
();
ClipboardSelectionOwner
=
PrimarySelectionOwner
=
0
;
selectionWindow
=
0
;
selectionAcquired
=
S_NOSELECTION
;
ClipboardSelectionOwner
=
PrimarySelectionOwner
=
0
;
selectionWindow
=
0
;
}
}
...
...
windows/x11drv/wineclipsrv.c
View file @
56ab55d3
...
...
@@ -3,50 +3,123 @@
*
* Copyright 1999 Noel Borthwick
*
* 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:
* This file contains the implementation for the Clipboard server
*
* TODO:
* 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 <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <stdio.h>
/* Lightweight debug definitions */
/*
* 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) */
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 __DPRINTF(dbname) (printf("%s:%s:%s ", dbname, 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(
"TRACE"
)
#define TRACE __DPRINTF(
__DBCL_TRACE
)
#else
#define TRACE __DUMMY_DPRINTF
#endif
/* NO_TRACE_MSGS */
#ifndef NO_DEBUG_MSGS
#define WARN __DPRINTF(
"WARN"
)
#define FIXME __DPRINTF(
"FIXME"
)
#define WARN __DPRINTF(
__DBCL_WARN
)
#define FIXME __DPRINTF(
__DBCL_FIXME
)
#else
#define WARN __DUMMY_DPRINTF
#define FIXME __DUMMY_DPRINTF
#endif
/* NO_DEBUG_MSGS */
#define ERR __DPRINTF("ERROR")
/* 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
...
...
@@ -62,10 +135,10 @@ static char *g_szOutOfMemory = "Insufficient memory!\n";
/* X selection context info */
static
char
_CLIPBOARD
[]
=
"CLIPBOARD"
;
/* CLIPBOARD atom name */
static
char
FMT_PREFIX
[]
=
"<WCF>"
;
/* Prefix for windows specific formats */
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
{
...
...
@@ -119,7 +192,6 @@ void getGC(Window win, GC *gc);
void
main
(
int
argc
,
char
**
argv
)
{
XEvent
event
;
unsigned
int
width
,
height
;
/* window size */
if
(
!
Init
(
argc
,
argv
)
)
exit
(
0
);
...
...
@@ -130,6 +202,8 @@ void main(int argc, char **argv)
*/
if
(
AcquireSelection
()
==
S_NOSELECTION
)
TerminateServer
(
0
);
TRACE
(
"Clipboard server running...
\n
"
);
/* Start an X event loop */
while
(
1
)
...
...
@@ -243,8 +317,23 @@ BOOL Init(int argc, char **argv)
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
]);
TRACE
(
"Clipboard server running...
\n
"
);
__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
;
}
...
...
@@ -287,27 +376,39 @@ int AcquireSelection()
{
TRACE
(
"Acquiring PRIMARY selection...
\n
"
);
g_cPrimaryTargets
=
CacheDataFormats
(
XA_PRIMARY
,
&
g_pPrimaryCache
);
if
(
g_cPrimaryTargets
)
XSetSelectionOwner
(
g_display
,
XA_PRIMARY
,
g_win
,
CurrentTime
);
else
TRACE
(
"No PRIMARY targets - ownership not acquired.
\n
"
);
TRACE
(
"Cached %ld formats...
\n
"
,
g_cPrimaryTargets
);
}
if
(
g_selectionToAcquire
&
S_CLIPBOARD
)
{
TRACE
(
"Acquiring CLIPBOARD selection...
\n
"
);
g_cClipboardTargets
=
CacheDataFormats
(
xaClipboard
,
&
g_pClipboardCache
);
if
(
g_cClipboardTargets
)
XSetSelectionOwner
(
g_display
,
xaClipboard
,
g_win
,
CurrentTime
);
else
TRACE
(
"No CLIPBOARD targets - ownership not acquired.
\n
"
);
TRACE
(
"Cached %ld formats...
\n
"
,
g_cClipboardTargets
);
}
/* Remember the acquired selections */
if
(
XGetSelectionOwner
(
g_display
,
XA_PRIMARY
)
==
g_win
)
/*
* 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
;
if
(
XGetSelectionOwner
(
g_display
,
xaClipboard
)
==
g_win
)
}
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
;
}
...
...
@@ -398,7 +499,7 @@ int CacheDataFormats( Atom SelectionSrc, PCACHEENTRY *ppCache )
/* Populate the cache entry */
if
(
!
FillCacheEntry
(
SelectionSrc
,
targetList
[
i
],
&
((
*
ppCache
)[
i
])))
ERR
(
"Failed to fill cache entry!"
);
ERR
(
"Failed to fill cache entry!
\n
"
);
XFree
(
itemFmtName
);
}
...
...
@@ -453,8 +554,11 @@ BOOL FillCacheEntry( Atom SelectionSrc, Atom target, PCACHEENTRY pCacheEntry )
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
)
);
...
...
@@ -600,7 +704,7 @@ void EmptyCache(PCACHEENTRY pCache, int nItems)
}
else
{
TRACE
(
"Freeing %s (
0x%x
)...
\n
"
,
TRACE
(
"Freeing %s (
%p
)...
\n
"
,
XGetAtomName
(
g_display
,
pCache
[
i
].
target
),
pCache
[
i
].
pData
);
/* Free the cached data item (allocated by X) */
...
...
@@ -621,8 +725,10 @@ void EmptyCache(PCACHEENTRY pCache, int nItems)
*/
void
EVENT_ProcessEvent
(
XEvent
*
event
)
{
// TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
/*
TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
*/
switch
(
event
->
type
)
{
case
Expose
:
...
...
@@ -652,7 +758,7 @@ void EVENT_ProcessEvent( XEvent *event )
break
;
case
PropertyNotify
:
EVENT_PropertyNotify
(
(
XPropertyEvent
*
)
event
);
//
EVENT_PropertyNotify( (XPropertyEvent *)event );
break
;
default:
/* ignore all other events */
...
...
@@ -771,7 +877,6 @@ void EVENT_SelectionRequest( XSelectionRequestEvent *event, BOOL bIsMultiple )
XSelectionEvent
result
;
Atom
rprop
=
None
;
Window
request
=
event
->
requestor
;
BOOL
couldOpen
=
FALSE
;
Atom
xaMultiple
=
XInternAtom
(
g_display
,
"MULTIPLE"
,
False
);
PCACHEENTRY
pCacheEntry
=
NULL
;
void
*
pData
=
NULL
;
...
...
@@ -803,7 +908,7 @@ void EVENT_SelectionRequest( XSelectionRequestEvent *event, BOOL bIsMultiple )
}
/* Update the X property */
TRACE
(
"
\t
Updating property %s..."
,
XGetAtomName
(
g_display
,
rprop
));
TRACE
(
"
\t
Updating property %s...
\n
"
,
XGetAtomName
(
g_display
,
rprop
));
/* If we have a request for a pixmap, return a duplicate */
...
...
@@ -853,17 +958,36 @@ void EVENT_SelectionClear( XSelectionClearEvent *event )
TRACE
(
"()
\n
"
);
if
(
event
->
selection
==
XA_PRIMARY
)
/* 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
)
)
{
g_selectionAcquired
&=
~
S_PRIMARY
;
/* Clear the PRIMARY flag */
TRACE
(
"Lost PRIMARY selection...
\n
"
);
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
==
xaClipboard
)
else
if
(
event
->
selection
==
XA_PRIMARY
)
{
g_selectionAcquired
&=
~
S_CLIPBOARD
;
/* Clear the CLIPBOARD flag */
TRACE
(
"Lost CLIPBOARD selection...
\n
"
);
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
);
...
...
@@ -915,7 +1039,7 @@ Pixmap DuplicatePixmap(Pixmap pixmap)
unsigned
border_width
;
/* Unused */
unsigned
int
depth
,
width
,
height
;
TRACE
(
"
\t
() Pixmap=%
ul
\n
"
,
pixmap
);
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
,
...
...
@@ -933,7 +1057,7 @@ Pixmap DuplicatePixmap(Pixmap pixmap)
XDestroyImage
(
xi
);
TRACE
(
"
\t
() New Pixmap=%
ul
\n
"
,
newPixmap
);
TRACE
(
"
\t
() New Pixmap=%
ld
\n
"
,
(
long
)
newPixmap
);
return
newPixmap
;
}
...
...
wine.ini
View file @
56ab55d3
...
...
@@ -158,5 +158,9 @@ Startup=
;InitialColumns=80
;TerminalType=nxterm
[Clipboard]
ClearAllSelections
=
0
PersistentSelection
=
1
# </wineconf>
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