espanso/espanso-ui/src/mac/AppDelegate.mm
2021-08-06 19:41:59 +02:00

149 lines
4.7 KiB
Plaintext

/*
* This file is part of espanso.
*
* Copyright (C) 2019-2021 Federico Terzi
*
* espanso is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* espanso is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
#import "AppDelegate.h"
void addSeparatorMenu(NSMenu * parent);
void addSingleMenu(NSMenu * parent, id item);
void addSubMenu(NSMenu * parent, NSArray * items);
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
if (options.show_icon) {
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
[self setIcon: 0];
}
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
// Heartbeat timer setup
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(heartbeatHandler:)
userInfo:nil
repeats:YES];
}
- (void) setIcon: (int32_t)iconIndex {
if (options.show_icon) {
char * iconPath = options.icon_paths[iconIndex];
NSString *nsIconPath = [NSString stringWithUTF8String:iconPath];
NSImage *statusImage = [[NSImage alloc] initWithContentsOfFile:nsIconPath];
[statusImage setTemplate:YES];
[statusItem.button setImage:statusImage];
[statusItem setHighlightMode:YES];
[statusItem.button setAction:@selector(statusIconClick:)];
[statusItem.button setTarget:self];
}
}
- (IBAction) statusIconClick: (id) sender {
UIEvent event = {};
event.event_type = UI_EVENT_TYPE_ICON_CLICK;
if (event_callback && rust_instance) {
event_callback(rust_instance, event);
}
}
- (void) popupMenu: (NSString *) payload {
NSError *jsonError;
NSData *data = [payload dataUsingEncoding:NSUTF8StringEncoding];
NSArray *jsonMenuItems = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Espanso"];
addSubMenu(menu, jsonMenuItems);
[statusItem popUpStatusItemMenu: menu];
}
- (IBAction) contextMenuClick: (id) sender {
NSInteger itemId = [[sender valueForKey:@"tag"] integerValue];
UIEvent event = {};
event.event_type = UI_EVENT_TYPE_CONTEXT_MENU_CLICK;
event.context_menu_id = (uint32_t) [itemId intValue];
if (event_callback && rust_instance) {
event_callback(rust_instance, event);
}
}
- (void) showNotification: (NSString *) message withDelay: (double) delay {
NSUserNotification *notification = [[NSUserNotification alloc] init];
notification.title = @"Espanso";
notification.informativeText = message;
notification.soundName = nil;
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
[[NSUserNotificationCenter defaultUserNotificationCenter] performSelector:@selector(removeDeliveredNotification:) withObject:notification afterDelay:delay];
}
- (void) heartbeatHandler: (NSTimer *)timer {
UIEvent event = {};
event.event_type = UI_EVENT_TYPE_HEARTBEAT;
if (event_callback && rust_instance) {
event_callback(rust_instance, event);
}
}
@end
// Menu utility methods
void addSeparatorMenu(NSMenu * parent)
{
[parent addItem: [NSMenuItem separatorItem]];
}
void addSingleMenu(NSMenu * parent, id item)
{
id label = [item objectForKey:@"label"];
id raw_id = [item objectForKey:@"id"];
if (label == nil || raw_id == nil)
{
return;
}
NSMenuItem *newMenu = [[NSMenuItem alloc] initWithTitle:label action:@selector(contextMenuClick:) keyEquivalent:@""];
[newMenu setTag:(NSInteger)raw_id];
[parent addItem: newMenu];
}
void addSubMenu(NSMenu * parent, NSArray * items)
{
for (id item in items) {
id type = [item objectForKey:@"type"];
if ([type isEqualToString:@"simple"])
{
addSingleMenu(parent, item);
}
else if ([type isEqualToString:@"separator"])
{
addSeparatorMenu(parent);
}
else if ([type isEqualToString:@"sub"])
{
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:[item objectForKey:@"label"] action:nil keyEquivalent:@""];
NSMenu *subMenu = [[NSMenu alloc] init];
[parent addItem: menuItem];
addSubMenu(subMenu, [item objectForKey:@"items"]);
[menuItem setSubmenu: subMenu];
}
}
}