added handling for DestroyNotify of clipboard requestors.

This commit is contained in:
crs 2002-04-25 10:43:53 +00:00
parent f63d0e4ada
commit 7d9fa41514
4 changed files with 67 additions and 15 deletions

View File

@ -86,6 +86,12 @@ void CXWindowsSecondaryScreen::run()
xevent.xproperty.time);
}
break;
case DestroyNotify:
// looks like one of the windows that requested a clipboard
// transfer has gone bye-bye.
destroyClipboardRequest(xevent.xdestroywindow.window);
break;
}
}
}

View File

@ -160,6 +160,12 @@ void CXWindowsPrimaryScreen::run()
xevent.xproperty.time);
}
break;
case DestroyNotify:
// looks like one of the windows that requested a clipboard
// transfer has gone bye-bye.
destroyClipboardRequest(xevent.xdestroywindow.window);
break;
}
}
}

View File

@ -578,6 +578,7 @@ void CXWindowsScreen::processClipboardRequest(
return;
}
CRequestList* list = index->second;
assert(list != NULL);
// find the property in the list
CRequestList::iterator index2;
@ -591,6 +592,7 @@ void CXWindowsScreen::processClipboardRequest(
return;
}
CClipboardRequest* request = *index2;
assert(request != NULL);
// compute amount of data to send
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
// it from the list and, if the list is empty, the list from the
// map.
list->erase(index2);
delete request;
if (list->empty()) {
m_requests.erase(index);
delete list;
// map. also stop watching the requestor for events.
if (count == 0) {
list->erase(index2);
delete request;
if (list->empty()) {
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(
Window requestor, Atom target,
Atom property, Time time)
@ -658,15 +690,6 @@ bool CXWindowsScreen::sendClipboardData(
if (data.size() > kMaxRequestSize) {
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
CRequestList* list = m_requests[requestor];
if (list == NULL) {
@ -685,6 +708,20 @@ bool CXWindowsScreen::sendClipboardData(
// add request to request list
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 {
log((CLOG_DEBUG "handling clipboard request for %d", target));

View File

@ -81,6 +81,9 @@ class CXWindowsScreen {
void processClipboardRequest(Window window,
Atom property, Time time);
// terminate a selection request
void destroyClipboardRequest(Window window);
// called by openDisplay() to allow subclasses to prepare the display
virtual void onOpenDisplay() = 0;