I'm wondering what the correct, or recommended, way is to dismiss a SwiftUI that is being presented as a sheet hosted by an NSHostingController. The usual technique of invoking @Environment(\.dismiss) does not appear to work.
Consider the code below. An NSWindowController is attempting to display a SwiftUI SettingsView as a sheet. The sheet is correctly presented, but the SettingsView is unable to dismiss itself.
I am able to make it work by passing a closure into SettingsView that calls back to the NSWindowController but it's rather convoluted because SettingsView doesn't know the view controller that's hosting it until after SettingsView has been created, which means "finding" that view controller in the window controller to dismiss is more involved than it should be.
Is there a better strategy to leverage here?
final class MyViewController: NSViewController {
@IBAction func buttonClicked(_ sender: NSButton) {
if let presenter = window?.contentViewController {
presenter.presentAsSheet(NSHostingController(rootView: SettingsView()))
}
}
}
struct SettingsView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
Button("Cancel", role: .cancel) {
dismiss() // This call does not dismiss the sheet.
} .keyboardShortcut(.cancelAction)
}
}
}
Thank you.
macOS 15.4.1 (24E263), Xcode 16.3 (16E140)
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
In the header for UIViewController, the method dismissViewControllerAnimated is declared like this:
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion NS_SWIFT_DISABLE_ASYNC API_AVAILABLE(ios(5.0));
NS_SWIFT_DISABLE_ASYNC means that there's no async version exposed like there would normally be of a method that exposes a completion handler. Why is this? And is it unwise / unsafe for me to make my own async version of it using a continuation?
My use case is that I want a method that will sequentially dismiss all view controllers presented by a root view controller. So I could have this extension on UIViewController:
extension UIViewController {
func dismissAsync(animated: Bool) async {
await withCheckedContinuation { continuation in
self.dismiss(animated: animated) {
continuation.resume()
}
}
}
func dismissPresentedViewControllers() async {
while self.topPresentedViewController != self {
await self.topPresentedViewController.dismissAsync(animated: true)
}
}
var topPresentedViewController: UIViewController {
var result = self
while result.presentedViewController != nil {
result = result.presentedViewController!
}
return result
}
Hi,
I am currently developing a document-based application for macOS and have encountered a challenge related to document container management. Specifically, I need to open a windowGroup that shares the same container as the one used in the DocumentGroup. However, my current approach of using a global shared model container has led to unintended behavior: any new document created is linked to existing ones, and changes made in one document are reflected across all documents.
To address this issue, I am looking for a solution that allows each newly created document to be individualized while still sharing the document container with all relevant WindowGroups that require access to the data it holds. I would greatly appreciate any insights or recommendations you might have on how to achieve this.
Thank you for your time and assistance.
Best regards,
Something like:
@main
struct Todo: App {
var body: some Scene {
DocumentGroup(editing: Item.self, contentType: .item) {
ContentView()
}
WindowGroup {
UndockView()
.modelContainer(of documentGroup above)
}
}
}
I am experiencing memory leaks in my iOS app that seem to be related to an issue between UIInputView and _UIInputViewContent. After using the memory graph, I'm seeing that instances of these objects aren't being deallocated properly.
The UIInputViewController whichs holds the inputView is being deallocated properly along with its subviews.I have tried to remove all of UIInputViewController's subviews and their functions but the uiInputView is not being deallocated.
The current setup of my app is a collectionView with multiple cell,each possessing a textfield with holds a UIInputViewController.When i scroll up or down,the views are being reused as expected and the number of UIInputViewController stays consistent with the number of textfields.However the number of inputView keeps increasing referencing solely _UIInputViewContent.
class KeyboardViewController: UIInputViewController {
// Callbacks
var key1: ((String) -> Void)?
var key2: (() -> Void)?
var key3: (() -> Void)?
var key4: (() -> Void)?
private lazy var buttonTitles = [
["1", "2", "3"],
["4", "5", "6"],
["7", "8", "9"]
]
override func viewDidLoad() {
super.viewDidLoad()
setupKeyboard()
}
lazy var mainStackView: UIStackView = {
let mainStackView = UIStackView()
mainStackView.axis = .vertical
mainStackView.distribution = .fillEqually
mainStackView.spacing = 16
mainStackView.translatesAutoresizingMaskIntoConstraints = false
return mainStackView
}()
private func setupKeyboard() {
let keyboardView = UIView(frame:CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 279.0))
keyboardView.addSubview(mainStackView)
NSLayoutConstraint.activate([
mainStackView.topAnchor.constraint(equalTo: keyboardView.topAnchor, constant: 16),
mainStackView.leadingAnchor.constraint(equalTo: keyboardView.leadingAnchor, constant: 0),
mainStackView.trailingAnchor.constraint(equalTo: keyboardView.trailingAnchor, constant: -24),
mainStackView.bottomAnchor.constraint(equalTo: keyboardView.bottomAnchor, constant: -35)
])
// Create rows
for (_, _) in buttonTitles.enumerated() {
let rowStackView = UIStackView()
rowStackView.axis = .horizontal
rowStackView.distribution = .fillEqually
rowStackView.spacing = 1
// Create buttons for each row
for title in rowTitles {
let button = createButton(title: title)
rowStackView.addArrangedSubview(button)
}
mainStackView.addArrangedSubview(rowStackView)
}
self.view = keyboardView
}
private func createButton(title: String) -> UIButton {
switch title {
///returns a uibutton based on title
}
}
// MARK: - Button Actions
@objc private func numberTapped(_ sender: UIButton) {
if let number = sender.title(for: .normal) {
key1?(number)
}
}
@objc private func key2Called() {
key2?()
}
@objc private func key3Called() {
key3?()
}
@objc private func key4Called() {
key4?()
}
deinit {
// Clear any strong references
key1 = nil
key2 = nil
key3 = nil
key4 = nil
for subview in mainStackView.arrangedSubviews {
if let stackView = subview as? UIStackView {
for button in stackView.arrangedSubviews {
(button as? UIButton)?.removeTarget(self, action: nil, for: .allEvents)
}
}
}
mainStackView.removeFromSuperview()
}
}
Environment
iOS 16.3
Xcode 18.3.1
Any insights would be greatly appreciated as this is causing noticeable memory growth in my app over time.
In my CarPlay app, I am hiding the navigation bar by using the following:
self.mapTemplate?.automaticallyHidesNavigationBar = true
self.mapTemplate?.hidesButtonsWithNavigationBar = false
I don't want the navigation bar to show unless a user interacts with the map by tapping it.
Strangely, when I present a CPNavigationAlert the navigation bar will often appear and then disappear after the alert is dismissed.
Is there a setting or reason that the navigation bar would be appearing when presenting this alert? I would like to keep the nav bar hidden during this time.
As the title says, I am not sure how to properly build an inverted ScrollView where I can safely insert items above my data ("prepend") without everything jumping around.
My current code is essentially this:
@State private var scrollPosition = ScrollPosition(idType: Message.ID.self)
private func onMessageDidScrollIntoView(_ id: Message.ID) {
let indexOfVisibleMessage = /* ... */
if indexOfVisibleMessage < 10 {
fetchOlderMessages()
// ^ this updates my ViewModel `messages`
}
}
var body: some View {
ScrollView {
LazyVStack {
ForEach(messages) { message in
MessageCell(message)
}
}.scrollTargetLayout()
}
.defaultScrollAnchor(.bottom)
.scrollPosition($scrollPosition)
.onChange(of: scrollPosition) { oldValue, newValue in
guard let visibleMessageId = scrollPosition.viewID(type: Message.ID.self) else { return }
onMessageDidScrollIntoView(visibleMessageId)
}
}
..so if the user scrolls up to the oldest 10 messages, I start loading more and insert them at the top.
The problem with this is that the ScrollView now jumps when new messages are inserted. This is because the ScrollView maintains it's Y position, but the content size changes since we are adding new items "above".
I tried to play around with a few suggestions I found on StackOverflow, namely;
Inverting the ScrollView (.scaleEffect(y: -1) on the ScrollView and then again on the MessageCell to counter it): This somehow jumped the x position of the ScrollView and completely breaks .contextMenu.
Playing around with .onScrollGeometryChange to update scrollPosition.scrollTo(y:) when it's contentSize changes: This just didn't work and stopped the user scroll gesture/interaction.
Setting scrollPosition to the Message.ID I want to keep stable before doing an update: This didn't do anything.
But nothing actually worked for the reasons described above.
How do you actually build these UIs in SwiftUI? I think an inverted ScrollView is quite a common UI, and obviously data has to be loaded lazily.
We recently migrated our app to use NavigationSplitView on iPad with a sidebar and detail setup, and we got reports that the navigation buttons on the sidebar disappear when returning to our app after using a different app. I reproduced the issue from a new empty project with the following code (issue tested on iOS 17.4 and iOS 18.3, was not able to reproduce on iOS 16.4):
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
NavigationSplitView {
Text("sidebar")
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button(action: {}) {
Image(systemName: "square.and.arrow.down")
}
}
ToolbarItem(placement: .topBarTrailing) {
Button(action: {}) {
Image(systemName: "square.and.arrow.up")
}
}
}
} detail: {
Text("detail")
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button(action: {}) {
Image(systemName: "eraser")
}
}
ToolbarItem(placement: .topBarTrailing) {
Button(action: {}) {
Image(systemName: "pencil")
}
}
}
}
}
}
}
Please check the following GIF for the simple steps, notice how the navbar buttons in the detail view do not disappear:
Here's the console output, it shows that the constraints break internally:
I am a developer on an enterprise application. Our team just updated our pipeline to build our app on the iOS 18 SDK instead of the 17.4 SDK and this has caused a lot of our ui elements to change and several crashes within the app resulting in just the simple error message "Swift runtime failure: unhandled C++ / Objective-C exception".
Why is just updating the SDK causing all these issues? Is there anyway to keep the previous version or will we have to go component by component to fix the constraints and crashes? These issues seem to be happening to our users on iOS 18 and beyond.
Hi! I'm seeing some weird animation issues building the Food Truck sample application.^1 I'm running from macOS 15.4 and Xcode 16.3. I'm building the Food Truck application for macOS. I'm not focusing on iOS for now.
The FoodTruckModel adds new Order values with an animation:
// FoodTruckModel.swift
withAnimation(.spring(response: 0.4, dampingFraction: 1)) {
self.orders.append(orderGenerator.generateOrder(number: orders.count + 1, date: .now, generator: &generator))
}
This then animates the OrdersTable when new Order values are added.
Here is a small change to OrdersTable:
// OrdersTable.swift
- @State private var sortOrder = [KeyPathComparator(\Order.status, order: .reverse)]
+ @State private var sortOrder = [KeyPathComparator(\Order.creationDate, order: .reverse)]
Running the app now inserts new Order values at the top.
The problem is I seem to be seeing some weird animation issues here. It seems that as soon as the new Order comes in there is some kind of weird glitch where it appears as if part the animation is coming from the side instead of down from the top:
What's then more weird is that if I seem to affect the state of the Table in any way then the next Order comes in with perfect animation.
Scrolling the Table fixes the animation.
Changing the creationData sort order from reverse to forward and back to reverse fixes the animation.
Any ideas? Is there something about how the Food Truck product is built that would cause this to happen? Is this an underlying issue in the SwiftUI infra?
Hi, I'm working on RealityView and I have two entities in RCP. In order to set views for both entities, I have to create two separate attachments for each entity. What I want to achieve is that when I hover (by eye) on one entity's attachment, it would trigger the hover effect of the other entity's attachment. I try to use the hoverEffectGroup, but it would only activate the hover effect in a subview, instead a complete separate view. I refer to the following WWDC instruction for the hover effect.
https://developer.apple.com/videos/play/wwdc2024/10152/
Description
When using UIDocumentPickerViewController with allowsMultipleSelection = false, I expect that selecting a file will dismiss only the document picker.
However, if a user quickly taps the same file multiple times, the picker dismisses both itself and the presenting view controller (i.e., it pops two levels from the view controller stack), which leads to unintended behavior and breaks presentation flow.
Expected Behavior
Only UIDocumentPickerViewController should be dismissed when a file is selected—even if the user taps quickly or multiple times on the same file.
Actual Behavior
When tapping the same file multiple times quickly, the picker dismisses not only itself but also the parent view controller it was presented from.
Steps to Reproduce
Create a simple view controller and present another one modally over it.
From that presented view controller, present a UIDocumentPickerViewController with allowsMultipleSelection = false.
Tap quickly on the same file in the picker 2 times.
Result: Both the document picker and the presenting view controller are dismissed.
Reproducible Code Snippet
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
addLabel("Parent View Controller")
DispatchQueue.main.async { [unowned self] in
let child = UIViewController()
child.view.backgroundColor = .yellow
present(child, animated: true)
child.addLabel("Child View Controller")
let vc = UIDocumentPickerViewController(
forOpeningContentTypes: [.pdf, .jpeg, .png],
asCopy: true
)
vc.allowsMultipleSelection = false
child.present(vc, animated: true)
}
}
}
extension UIViewController {
func addLabel(_ text: String) {
let label = UILabel(frame: CGRect(x: 0, y: 50, width: view.bounds.width, height: 30))
label.text = text
view.addSubview(label)
}
}
Environment
Device: iPhone 15 Pro and others
iOS version: 18.2 (reproduces on multiple iOS versions)
Occurs with: .pdf, .jpeg, .png file types
Mode: Both simulator and real device
Notes
Happens consistently with fast multiple taps on the same file.
This breaks expected view controller stack behavior.
I am facing same issue with major crash while coming out from this function.
Basically using collectionView.dequeReusableCell with size calculation.
func getSizeOfFavouriteCell(_ collectionView: UICollectionView, at indexPath: IndexPath, item: FindCircleInfoCellItem) -> CGSize { guard let dummyCell = collectionView.dequeueReusableCell( withReuseIdentifier: TAButtonAddCollectionViewCell.reuseIdentifier, for: indexPath) as? TAButtonAddCollectionViewCell else { return CGSize.zero }
dummyCell.title = item.title
dummyCell.subtitle = item.subtitle
dummyCell.icon = item.icon
dummyCell.layoutIfNeeded()
var targetSize = CGSize.zero
if viewModel.favoritesDataSource.isEmpty.not,
viewModel.favoritesDataSource.count > FindSheetViewControllerConstants.minimumFavoritesToDisplayInSection {
targetSize = CGSize(width: collectionView.frame.size.width / 2, height: collectionView.frame.height)
var estimatedSize: CGSize = dummyCell.systemLayoutSizeFitting(targetSize)
if estimatedSize.width > targetSize.width {
estimatedSize.width = targetSize.width
}
return CGSize(width: estimatedSize.width, height: targetSize.height)
}
}
We have resolve issue with size calculation with checking nil. Working fine in xcode 15 and 16+.
Note: Please help me with reason of crash? Is it because of xCode 16.2 onwards **strict check on UICollectionView **
I am developing an application which make use of 2 ornaments anchored to a volumetric window, one used a toolbar and one to display different views.
The problem I am facing consistently is that the ornaments seems to scale up or down after moving the volume using the OS handle or starting a GroupActivity session.
This first image shows the ornaments as soon as I started the app, no dragging nor group activities:
This second images shows them as soon as I join a group activity session:
The map, which might seem smaller, has not been touched and has always the same scale.
In this last image I had just dragged the entire volume using the OS toolbar, resulting in the ornaments scaling down:
This is how the volume and the ornaments are declared:
WindowGroup(id: "CityVolume") {
let cityVM = CityViewModel(volumeSize: CityView.initialVolumeSize)
CityView(cityVM: cityVM)
.ornament(attachmentAnchor: .scene(.bottomFront)) {
HStack {
TourismChartsButton()
LandmarksListButton()
CenterMapButton()
ToggleImmersiveSpaceButton()
TrafficDataButton()
BusLinesButton()
}
.padding()
.offset(z: 10)
.rotation3DEffect(Angle(degrees: 15), axis: (x: 1.0, y: 0.0, z: 0.0))
}
.ornament(attachmentAnchor: .scene(.back)) {
ZStack {
if AppModel.Instance.tourismVM.isChartViewVisible {
TourismChartsView()
}
if AppModel.Instance.busLinesVM.isDataViewEnabled {
BusLineView()
}
}
}
.task(observeGroupActivity)
.onAppear {
appModel.cityVM = cityVM
}
}
.windowStyle(.volumetric)
.windowResizability(.contentSize)
.volumeWorldAlignment(.gravityAligned)
.defaultSize(CityView.initialVolumeSize, in: .meters)
It happens also without starting a SharePlay session, but not as frequently as during SharePlay. Experienced the same behaviour with toolbars.
Am I doing something wrong with how I created the ornaments? Am I missing something?
Hello,
is there a way to implement Continuity Markup in our own apps?
(This is what I'm talking about: https://support.apple.com/en-us/102269 , scroll down to "Use Continuity Markup").
Also, why does a QuickLook panel (QLPreviewPanel.shared()) not display the markup options when triggered from my app for png image files in my app's Group Container? Do I need to implement certain NSServicesMenuRequestor methods for that?
Sadly, I could not find any docs on that.
Thank you,
– Matthias
I'm trying to update my app to use TextKit 2. The one thing that I'm still not sure about is how I can get the selection frame. My app uses it to auto-scroll the text to keep the cursor at the same height when the text wraps onto a new line or a newline is manually inserted. Currently I'm using NSLayoutManager.layoutManager!.boundingRect(forGlyphRange:in:).
The code below almost works. When editing the text or changing the selection, the current selection frame is printed out. My expectation is that the selection frame after a text or selection change should be equal to the selection frame before the next text change. I've noticed that this is not always true when the text has a NSParagraphStyle with spacing > 0. As long as I type at the end of the text, everything's fine, but if I insert some lines, then move the selection somewhere into the middle of the text and insert another newline, the frame printed after manually moving the selection is different than the frame before the newline is inserted. It seems that the offset between the two frames is exactly the same as the paragraph style's spacing. Instead when moving the selection with the arrow key the printed frames are correct.
I've filed FB17104954.
class ViewController: NSViewController, NSTextViewDelegate {
private var textView: NSTextView!
override func loadView() {
let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
textView = NSTextView(frame: scrollView.frame)
textView.autoresizingMask = [.width, .height]
textView.delegate = self
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 40
textView.typingAttributes = [.foregroundColor: NSColor.labelColor, .paragraphStyle: paragraphStyle]
scrollView.documentView = textView
scrollView.hasVerticalScroller = true
view = scrollView
}
func textView(_ textView: NSTextView, shouldChangeTextIn affectedCharRange: NSRange, replacementString: String?) -> Bool {
print("before", selectionFrame.maxY, selectionFrame)
return true
}
func textDidChange(_ notification: Notification) {
print("after ", selectionFrame.maxY, selectionFrame)
}
func textViewDidChangeSelection(_ notification: Notification) {
print("select", selectionFrame.maxY, selectionFrame)
}
var selectionFrame: CGRect {
guard let selection = textView.textLayoutManager!.textSelections.first?.textRanges.first else {
return .null
}
var frame = CGRect.null
textView.textLayoutManager!.ensureLayout(for: selection)
textView.textLayoutManager!.enumerateTextSegments(in: selection, type: .selection, options: [.rangeNotRequired]) { _, rect, _, _ in
frame = rect
return false
}
return frame
}
}
The behavior of the Button in ScrollView differs depending on how the View is displayed modally.
When the View is displayed as a .fullScreenCover, if the button is touched and scrolled without releasing the finger, the touch event is canceled and the action of the Button is not called.
On the other hand, if the View is displayed as a .sheet, the touch event is not canceled even if the view is scrolled without lifting the finger, and the action is called when the finger is released.
In order to prevent accidental interaction, I feel that the behavior of .fullScreenCover is better, as it cancels the event immediately when scrolling. Can I change the behavior of .sheet?
Demo movie is here:
https://x.com/kenmaz/status/1896498312737611891
Sample code
import SwiftUI
@main
struct SampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var showSheet = false
@State private var showFullScreen = false
var body: some View {
VStack(spacing: 16) {
Button("Sheet") {
showSheet.toggle()
}
Button("Full screen") {
showFullScreen.toggle()
}
}
.sheet(isPresented: $showSheet) {
SecondView()
}
.fullScreenCover(isPresented: $showFullScreen) {
SecondView()
}
.font(.title)
}
}
struct SecondView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
ScrollView {
Button("Dismiss") {
dismiss()
}
.buttonStyle(MyButtonStyle())
.padding(.top, 128)
.font(.title)
}
}
}
private struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration
.label
.foregroundStyle(.red)
.background(configuration.isPressed ? .gray : .clear)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
There's an easily reproducible SwiftUI bug on macOS where an app's UI state no longer updates/re-renders for "Designed for iPad" apps (i.e. ProcessInfo.processInfo.isiOSAppOnMac == true). The bug occurs in Xcode and also if the app is running independent of Xcode.
The bug occurs when:
the user Hides the app (i.e. it goes into the background)
the user puts the Mac to sleep (e.g. Apple menu > Sleep)
a total of ~60 seconds transpires (i.e. macOS puts the app into the "suspended state")
when the app is brought back into the foreground the UI no longer updates properly
The only way I have found to fix this is to manually open a new actual full app window via File > New, in which case the app works fine again in the new window.
The following extremely simple code in a default Xcode project illustrates the issue:
import SwiftUI
@main
struct staleApp: App {
@State private var isBright = true
var body: some Scene {
WindowGroup() {
ZStack {
(isBright ? Color.white : Color.black).ignoresSafeArea()
Button("TOGGLE") { isBright.toggle(); print("TAPPED") }
}
.onAppear { print("\(isBright ? "light" : "dark") view appeared") }
}
}
}
For the code above, after Hiding the app and putting the computer to sleep for 60 seconds or more, the button no longer swaps views, although the print statements still appear in the console upon tapping the button. Also, while in this buggy state, i can get the view to update to the current state (i.e. the view triggered by the last tap) by manually dragging the corner of the app window to resize the window. But after resizing, the view again does not update upon button tapping until I resize the window again.
so it appears the diff engine is mucked or that the Scene or WindowGroup are no longer correctly running on the main thread
I have tried rebuilding the entire view hierarchy by updating .id() on views but this approach does NOT work. I have tried many other options/hacks but have not been able to reset the 'view engine' other than opening a new window manually or by using: @Environment(.openWindow) private var openWindow
openWindow could be a viable solution except there's no way to programmatically close the old window for isiOSAppOnMac (@Environment(.dismissWindow) private var dismissWindow doesn't work for iOS)
I have a view with some buttons, and add 2 gestures using simultaneously. My app works well when built with XCode less than 16, or run on iOS less than 18.0.
Example code is below:
VStack(spacing: 0) {
Button {
print("button tapped")
} label: {
Rectangle()
.foregroundColor(.red)
}
.frame(height: 100)
}
.gesture(
DragGesture(minimumDistance: 0)
.onEnded { value in
print("single tap")
}
.simultaneously(with:
TapGesture(count: 2).onEnded {
print("double tap")
}
)
)
.frame(width: 200, height: 200)
.border(Color.purple)
I expect the action on Button should be recognized and print out button tapped, but only single tap and double tap are recognized
Hi,
I’m practicing with NavigationSplitView for macOS and customizing the sidebar. I’ve managed to adjust most parts, but I couldn’t remove the sidebar’s divider. It seems like it’s not possible in modern SwiftUI. My AppKit knowledge is also not very strong.
How can I remove the sidebar divider?
I want to use a plain background. I also solved it by creating my own sidebar, but I wanted to try it using NavigationSplitView.
Is there a way to detect when your apps (or any app I guess) is being moved by the user clicking and dragging the main window around the desktop at all?
I'm trying to find out if there's a way I can find out if a window is being clicked and dragged and whether there's certain triggers to the movement a little bit like shaking an iPhone with Shake to Undo.
Thanks