背景
在上篇博客中,我介绍了mouseSync这款软件的开发初衷、使用场景和开发的过程,感谢一些朋友试用该软件并给我留言,提出了一些新的需求和issue。同时也感谢开发者头条的推荐至头版的精选板块,让那篇开发笔记被2万开发者阅读过了,收获了github的star若干、公众号的关注若干、赞赏约50元。真的非常感谢大家的关注、star鼓励和金钱赞赏。
我整理了一下大家的需求,大体上可归纳为3类。
- 没有logo
- 在外部设备(鼠标/Trackpad真正属于的那台Mac)上容易引起误操作
- 一个关键的功能,左键拖拽功能,没有实现
在这篇博客中,我就来写一下对上面提到的三个需求的解决方案。完成上述三个需求后的软件在网盘可下载到,最新代码依然开源在github上。
需求
没有logo
其实这件事挺尴尬的,我不是设计师,因此平时logo的主要来源是flaticon,这次没忍心打扰正在熟睡的非著名设计师Joseph,因此还是在flaticon上找的icon,进行了简单的颜色变换与组合。
icon考虑到了mouseSync具有鼠标和蓝牙的特性,因此还是比较写实的。考虑到蓝牙客户端有外部设备和数据中心(两台Mac)之分,因此两个icon虽然很相似,但仍有细微的不同。不同点在于,数据中心的icon多了一个类似信号指示的标志,表示它是接收蓝牙信号的一端。
由于本人设计方面实在业余,还请大家轻喷。有空再找非著名设计师Joseph实现一枚漂亮的logo。
> icons
在外部设备端容易引起误操作
之前的demo视频中,为了让两台电脑看起来一致,我录的是同时打开文件,同时在图标上右击,在现实生活中,在同一时刻同时操作两台Mac的需求很少不存在。通常情况下,用户还是想对某一台Mac进行操作的。mouseSync的定位应该是:帮助用户用一个鼠标操作两台电脑,且给用户决定什么时候操作哪台,省去两个鼠标之间换来换去的麻烦。
之前的项目中,我对鼠标事件添加的均是全局监控事件,因此只要mouseSync生命周期没有结束,它的操作将实时被发送到另一台mac上。我想过两个解决方案:
- 跟其他共享键盘的软件一样,使用全局快捷键对蓝牙通知服务进行开启/关闭
- 将全局监控事件变成局部监控事件,蓝牙通知服务仅在应用视图为Keywindow时有效
为什么选择Plan B
关于方案1,我觉得作为一款软件,快捷键应当由用户自己决定,虽然cocoapod上已经有非常好的项目KeyHolder进行支持,但是考虑到两个因素还是决定使用Plan B。
先看看Plan B,Plan B是这样的,首先让当前的window全屏,但是里面没有内容,因此无论在当前试图下如何操作,都不会有可能造成误操作。回到Plan A,快捷键的录入放到哪里呢?如果放到当前视图,将会带来一定的误操作风险;如果放到MenuBar,那么用户将不得不退出全屏模式,到菜单栏进行设置,这样的解决方案破坏了用户体验,综合考虑,最终还是选了Plan B。
实现过程中遇到的问题
让当前窗口一打开就全屏的方法是在ViewDidLoad方法体中进行控制的:
|
|
但是我很快就发现了问题:尽管已经将应用全屏了,但是用户依然会有一定几率对dock栏和顶部菜单栏进行误操作。用户如果在操作另一台电脑的时候,还得注意这台电脑上是不是误操作了,这不符合我们软件开发的初衷。考虑到有些用户将dock放在底部,有些用户将dock放在左边,因此,我加了这样的限制,当用户将鼠标移动到距离屏幕边缘50px以内的时候,程序帮助他将鼠标移动至屏幕中央。参照下图,灰色地带就可以作为防止鼠标误操作的缓冲区。
> 防止对dock和菜单栏误操作解决方法示意图
阅读过上一篇博客的朋友一定注意到了,我们的程序是记录上一个鼠标点的位置,并将上一个鼠标点的位置与当前位置相减,将位置变动作为特征值进行发送。因此,在鼠标被程序移动到屏幕中央的时候,需要将上一个位置更新为屏幕中央的坐标。
|
|
左键拖拽功能
左键拖一个文件或窗口到一个新位置这个功能还是经常被使用到的,我使用的是Trackpad,通常是使用三支拖移。想要监听外围设备的这个动作并不难,但是想让计算机模拟这个操作相对比较困难。就像双击不是单纯的模拟单击事件两次一样,这次我又踩到坑了,drag and move事件并不是简单的mousedown-> mousemove -> mouseup这么容易的事情。
我在Stack Overflow上找到了正确的方法:有一个叫kCGEventLeftMouseDragged的事件,专门来处理这件事。
|
|
和Scroll滚轮事件一样,这里我们采用的是Quartz模拟鼠标事件,因此依然需要C与swift进行混编。模拟总共可分为3步:第一步是创建一个Quartz鼠标事件;第二步是将这个事件放到事件流中,并指定位置;第三步是release这个事件。
模拟这个事件的时候,随着鼠标拖拽后的不停移动,会不停产生event,而且event中x和y的偏移量始终是相对于第一次鼠标drag按下时的坐标。因此,我们需要记录两件事,第一件事是第一次drag时候的坐标,第二件事是当前是不是开启了新一轮的drag还是仍然在上一轮的drag中。核心代码如下:
|
|
上面的代码有两处需要注意:
- dragFirst初始值为true,在mouseUp之后重新置为true,表示一轮的drag已经完成了;
- y的坐标是-,x的坐标是+,这是由OS X的坐标系决定的。
最后,我用两台电脑同时在画板上写了一个牛B。mouseSync的开发工作算是告一段落了,希望对大家有所帮助!
> drag事件demo
Reference
- https://stackoverflow.com/questions/1817628/clicking-the-mouse-down-to-drag-objects-on-mac
- https://www.flaticon.com
结束
试用软件之后如果您对软件有任何的意见与建议,欢迎留言。如果您喜欢这款软件,也欢迎您将它推荐给您的朋友们。让我们一起将mouseSync变得更好!
我会在订阅号里不定期分享我个人的macOS/ios开发心得和开发笔记,也会在里面发表对于苹果产品/框架/趋势的拙见,希望爱好科技产品或者苹果生态圈的开发者关注。相信本公众号一定能给您带来收获和启发。
【欢迎扫码关注微信公众号】
> 扫码关注微信公众号 骨灰级果粉 获得最新文章更新
原文作者: Chih-Hao
原文链接: http://zhihaozhang.github.io/2017/09/29/mouseSyncII/
发表日期: September 29th 2017, 9:26:44 pm
版权声明: 本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可
-
Next Post元素加上边框和背景色 >为SVG中大小可变的
元素加上边框和背景色 -
Previous Post青芒 for Mac客户端开发笔记