added handling for DestroyNotify of clipboard requestors.
This commit is contained in:
parent
f63d0e4ada
commit
7d9fa41514
|
@ -86,6 +86,12 @@ void CXWindowsSecondaryScreen::run()
|
||||||
xevent.xproperty.time);
|
xevent.xproperty.time);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DestroyNotify:
|
||||||
|
// looks like one of the windows that requested a clipboard
|
||||||
|
// transfer has gone bye-bye.
|
||||||
|
destroyClipboardRequest(xevent.xdestroywindow.window);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,12 @@ void CXWindowsPrimaryScreen::run()
|
||||||
xevent.xproperty.time);
|
xevent.xproperty.time);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DestroyNotify:
|
||||||
|
// looks like one of the windows that requested a clipboard
|
||||||
|
// transfer has gone bye-bye.
|
||||||
|
destroyClipboardRequest(xevent.xdestroywindow.window);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -578,6 +578,7 @@ void CXWindowsScreen::processClipboardRequest(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CRequestList* list = index->second;
|
CRequestList* list = index->second;
|
||||||
|
assert(list != NULL);
|
||||||
|
|
||||||
// find the property in the list
|
// find the property in the list
|
||||||
CRequestList::iterator index2;
|
CRequestList::iterator index2;
|
||||||
|
@ -591,6 +592,7 @@ void CXWindowsScreen::processClipboardRequest(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CClipboardRequest* request = *index2;
|
CClipboardRequest* request = *index2;
|
||||||
|
assert(request != NULL);
|
||||||
|
|
||||||
// compute amount of data to send
|
// compute amount of data to send
|
||||||
assert(request->m_sent <= request->m_data.size());
|
assert(request->m_sent <= request->m_data.size());
|
||||||
|
@ -617,15 +619,45 @@ void CXWindowsScreen::processClipboardRequest(
|
||||||
|
|
||||||
// if we sent zero bytes then we're done sending this data. remove
|
// if we sent zero bytes then we're done sending this data. remove
|
||||||
// it from the list and, if the list is empty, the list from the
|
// it from the list and, if the list is empty, the list from the
|
||||||
// map.
|
// map. also stop watching the requestor for events.
|
||||||
list->erase(index2);
|
if (count == 0) {
|
||||||
delete request;
|
list->erase(index2);
|
||||||
if (list->empty()) {
|
delete request;
|
||||||
m_requests.erase(index);
|
if (list->empty()) {
|
||||||
delete list;
|
m_requests.erase(index);
|
||||||
|
delete list;
|
||||||
|
}
|
||||||
|
XSelectInput(m_display, requestor, NoEventMask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXWindowsScreen::destroyClipboardRequest(
|
||||||
|
Window requestor)
|
||||||
|
{
|
||||||
|
CLock lock(&m_mutex);
|
||||||
|
|
||||||
|
// find the request list
|
||||||
|
CRequestMap::iterator index = m_requests.find(requestor);
|
||||||
|
if (index == m_requests.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CRequestList* list = index->second;
|
||||||
|
assert(list != NULL);
|
||||||
|
|
||||||
|
// destroy every request in the list
|
||||||
|
for (CRequestList::iterator index2 = list->begin();
|
||||||
|
index2 != list->end(); ++index2) {
|
||||||
|
delete *index2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove and destroy the list
|
||||||
|
m_requests.erase(index);
|
||||||
|
delete list;
|
||||||
|
|
||||||
|
// note -- we don't stop watching the window for events because
|
||||||
|
// we're called in response to the window being destroyed.
|
||||||
|
}
|
||||||
|
|
||||||
bool CXWindowsScreen::sendClipboardData(
|
bool CXWindowsScreen::sendClipboardData(
|
||||||
Window requestor, Atom target,
|
Window requestor, Atom target,
|
||||||
Atom property, Time time)
|
Atom property, Time time)
|
||||||
|
@ -658,15 +690,6 @@ bool CXWindowsScreen::sendClipboardData(
|
||||||
if (data.size() > kMaxRequestSize) {
|
if (data.size() > kMaxRequestSize) {
|
||||||
log((CLOG_DEBUG "handling clipboard request for %d as INCR", target));
|
log((CLOG_DEBUG "handling clipboard request for %d as INCR", target));
|
||||||
|
|
||||||
// FIXME -- handle Alloc errors (by returning false)
|
|
||||||
// set property to INCR
|
|
||||||
const UInt32 zero = 0;
|
|
||||||
XChangeProperty(m_display, requestor, property,
|
|
||||||
m_atomINCR, 8 * sizeof(zero),
|
|
||||||
PropModeReplace,
|
|
||||||
reinterpret_cast<const unsigned char*>(&zero),
|
|
||||||
1);
|
|
||||||
|
|
||||||
// get the appropriate list, creating it if necessary
|
// get the appropriate list, creating it if necessary
|
||||||
CRequestList* list = m_requests[requestor];
|
CRequestList* list = m_requests[requestor];
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
|
@ -685,6 +708,20 @@ bool CXWindowsScreen::sendClipboardData(
|
||||||
|
|
||||||
// add request to request list
|
// add request to request list
|
||||||
list->push_back(request);
|
list->push_back(request);
|
||||||
|
|
||||||
|
// start watching requestor for property changes and
|
||||||
|
// destruction
|
||||||
|
XSelectInput(m_display, requestor, StructureNotifyMask |
|
||||||
|
PropertyChangeMask);
|
||||||
|
|
||||||
|
// FIXME -- handle Alloc errors (by returning false)
|
||||||
|
// set property to INCR
|
||||||
|
const UInt32 zero = 0;
|
||||||
|
XChangeProperty(m_display, requestor, property,
|
||||||
|
m_atomINCR, 8 * sizeof(zero),
|
||||||
|
PropModeReplace,
|
||||||
|
reinterpret_cast<const unsigned char*>(&zero),
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log((CLOG_DEBUG "handling clipboard request for %d", target));
|
log((CLOG_DEBUG "handling clipboard request for %d", target));
|
||||||
|
|
|
@ -81,6 +81,9 @@ class CXWindowsScreen {
|
||||||
void processClipboardRequest(Window window,
|
void processClipboardRequest(Window window,
|
||||||
Atom property, Time time);
|
Atom property, Time time);
|
||||||
|
|
||||||
|
// terminate a selection request
|
||||||
|
void destroyClipboardRequest(Window window);
|
||||||
|
|
||||||
// called by openDisplay() to allow subclasses to prepare the display
|
// called by openDisplay() to allow subclasses to prepare the display
|
||||||
virtual void onOpenDisplay() = 0;
|
virtual void onOpenDisplay() = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue