Skip to content

Commit

Permalink
Add missing call to CloseClipboard on windows (#1410)
Browse files Browse the repository at this point in the history
* Add missing call to `CloseClipboard`

* Update changelog

* Use a helper function to ensure `OpenClipbord` and `CloseClipboard` are always called together.
  • Loading branch information
andrewhickman authored Nov 19, 2020
1 parent 0b4e26f commit 14ad188
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 48 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ You can find its changes [documented below](#060---2020-06-01).
- Fixed `Either` not passing events to its hidden child correctly. ([#1351] by [@andrewhickman])
- Don't drop events while showing file dialogs ([#1302], [#1328] by [@jneem])
- Ensure that `LifeCycle::WidgetAdded` is the first thing a widget sees. ([#1259] by [@finnerale])
- Fix a missed call to `CloseClipboard` on Windows. ([#1410] by [@andrewhickman])

### Visual

Expand Down Expand Up @@ -536,6 +537,7 @@ Last release without a changelog :(
[#1259]: https://github.com/linebender/druid/pull/1259
[#1361]: https://github.com/linebender/druid/pull/1361
[#1371]: https://github.com/linebender/druid/pull/1371
[#1410]: https://github.com/linebender/druid/pull/1410

[Unreleased]: https://github.com/linebender/druid/compare/v0.6.0...master
[0.6.0]: https://github.com/linebender/druid/compare/v0.5.0...v0.6.0
Expand Down
92 changes: 44 additions & 48 deletions druid-shell/src/platform/windows/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ impl Clipboard {

/// Put multi-format data on the system clipboard.
pub fn put_formats(&mut self, formats: &[ClipboardFormat]) {
unsafe {
if OpenClipboard(ptr::null_mut()) == FALSE {
return;
}
with_clipboard(|| unsafe {
EmptyClipboard();

for format in formats {
Expand All @@ -69,16 +66,12 @@ impl Clipboard {
);
}
}
CloseClipboard();
}
});
}

/// Get a string from the system clipboard, if one is available.
pub fn get_string(&self) -> Option<String> {
unsafe {
if OpenClipboard(ptr::null_mut()) == FALSE {
return None;
}
with_clipboard(|| unsafe {
let handle = GetClipboardData(CF_UNICODETEXT);
if handle.is_null() {
None
Expand All @@ -88,16 +81,14 @@ impl Clipboard {
GlobalUnlock(handle);
result
}
}
})
.flatten()
}

/// Given a list of supported clipboard types, returns the supported type which has
/// highest priority on the system clipboard, or `None` if no types are supported.
pub fn preferred_format(&self, formats: &[FormatId]) -> Option<FormatId> {
unsafe {
if OpenClipboard(ptr::null_mut()) == FALSE {
return None;
}
with_clipboard(|| {
let format_ids = formats
.iter()
.map(|id| get_format_id(id))
Expand All @@ -107,10 +98,9 @@ impl Clipboard {
iter_clipboard_types().find(|available| format_ids.contains(&Some(*available)));
let format_idx =
first_match.and_then(|id| format_ids.iter().position(|i| i == &Some(id)));
let result = format_idx.map(|idx| formats[idx]);
CloseClipboard();
result
}
format_idx.map(|idx| formats[idx])
})
.flatten()
}

/// Return data in a given format, if available.
Expand All @@ -122,11 +112,7 @@ impl Clipboard {
return self.get_string().map(String::into_bytes);
}

unsafe {
if OpenClipboard(ptr::null_mut()) == FALSE {
return None;
}

with_clipboard(|| {
let format_id = match get_format_id(&format) {
Some(id) => id,
None => {
Expand All @@ -135,35 +121,45 @@ impl Clipboard {
}
};

if IsClipboardFormatAvailable(format_id) != 0 {
let handle = GetClipboardData(format_id);
let size = GlobalSize(handle);
let locked = GlobalLock(handle) as *const u8;
let mut dest = Vec::<u8>::with_capacity(size);
ptr::copy_nonoverlapping(locked, dest.as_mut_ptr(), size);
dest.set_len(size);
GlobalUnlock(handle);
CloseClipboard();
Some(dest)
} else {
None
unsafe {
if IsClipboardFormatAvailable(format_id) != 0 {
let handle = GetClipboardData(format_id);
let size = GlobalSize(handle);
let locked = GlobalLock(handle) as *const u8;
let mut dest = Vec::<u8>::with_capacity(size);
ptr::copy_nonoverlapping(locked, dest.as_mut_ptr(), size);
dest.set_len(size);
GlobalUnlock(handle);
Some(dest)
} else {
None
}
}
}
})
.flatten()
}

pub fn available_type_names(&self) -> Vec<String> {
unsafe {
if OpenClipboard(ptr::null_mut()) == FALSE {
return vec![];
}
}
let res = iter_clipboard_types()
.map(|id| format!("{}: {}", get_format_name(id), id))
.collect();
unsafe {
CloseClipboard();
with_clipboard(|| {
iter_clipboard_types()
.map(|id| format!("{}: {}", get_format_name(id), id))
.collect()
})
.unwrap_or_default()
}
}

fn with_clipboard<V>(f: impl FnOnce() -> V) -> Option<V> {
unsafe {
if OpenClipboard(ptr::null_mut()) == FALSE {
return None;
}
res

let result = f();

CloseClipboard();

Some(result)
}
}

Expand Down

0 comments on commit 14ad188

Please sign in to comment.