aboutsummaryrefslogtreecommitdiffstats
path: root/src/nsmenu.m
diff options
context:
space:
mode:
authorJuri Linkov2019-09-02 00:32:10 +0300
committerJuri Linkov2019-09-02 00:32:10 +0300
commit5bf45ec48b781a1165e882e7216892bf201d15f4 (patch)
tree2be92e4c40bb078796fa485ff92da43944a79e3e /src/nsmenu.m
parent51ac64d9aa6aec969c38a3774310479d1cbb4dc9 (diff)
downloademacs-5bf45ec48b781a1165e882e7216892bf201d15f4.tar.gz
emacs-5bf45ec48b781a1165e882e7216892bf201d15f4.zip
Try to add more tab-bar support on macos
Diffstat (limited to 'src/nsmenu.m')
-rw-r--r--src/nsmenu.m316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 817f8cff184..223561b9730 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -993,6 +993,322 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags,
993 993
994/* ========================================================================== 994/* ==========================================================================
995 995
996 Tabbar: externally-called functions
997
998 ========================================================================== */
999
1000void
1001free_frame_tab_bar (struct frame *f)
1002/* --------------------------------------------------------------------------
1003 Under NS we just hide the tabbar until it might be needed again.
1004 -------------------------------------------------------------------------- */
1005{
1006 EmacsView *view = FRAME_NS_VIEW (f);
1007
1008 NSTRACE ("free_frame_tab_bar");
1009
1010 block_input ();
1011 view->wait_for_tab_bar = NO;
1012
1013 /* Note: This triggers an animation, which calls windowDidResize
1014 repeatedly. */
1015 f->output_data.ns->in_animation = 1;
1016 [[view tabbar] setVisible: NO];
1017 f->output_data.ns->in_animation = 0;
1018
1019 unblock_input ();
1020}
1021
1022void
1023update_frame_tab_bar (struct frame *f)
1024/* --------------------------------------------------------------------------
1025 Update tabbar contents.
1026 -------------------------------------------------------------------------- */
1027{
1028 int i, k = 0;
1029 EmacsView *view = FRAME_NS_VIEW (f);
1030 EmacsTabbar *tabbar = [view tabbar];
1031 int oldh;
1032
1033 NSTRACE ("update_frame_tab_bar");
1034
1035 if (view == nil || tabbar == nil) return;
1036 block_input ();
1037
1038 oldh = FRAME_TABBAR_HEIGHT (f);
1039
1040#ifdef NS_IMPL_COCOA
1041 [tabbar clearActive];
1042#else
1043 [tabbar clearAll];
1044#endif
1045
1046 /* Update EmacsTabbar as in GtkUtils, build items list. */
1047 for (i = 0; i < f->n_tab_bar_items; ++i)
1048 {
1049#define TABPROP(IDX) AREF (f->tab_bar_items, \
1050 i * TAB_BAR_ITEM_NSLOTS + (IDX))
1051
1052 BOOL enabled_p = !NILP (TABPROP (TAB_BAR_ITEM_ENABLED_P));
1053 int idx;
1054 ptrdiff_t img_id;
1055 struct image *img;
1056 Lisp_Object image;
1057 Lisp_Object helpObj;
1058 const char *helpText;
1059
1060 /* Check if this is a separator. */
1061 if (EQ (TABPROP (TAB_BAR_ITEM_TYPE), Qt))
1062 {
1063 /* Skip separators. Newer macOS don't show them, and on
1064 GNUstep they are wide as a button, thus overflowing the
1065 tabbar most of the time. */
1066 continue;
1067 }
1068
1069 /* If image is a vector, choose the image according to the
1070 button state. */
1071 image = TABPROP (TAB_BAR_ITEM_IMAGES);
1072 if (VECTORP (image))
1073 {
1074 /* NS tabbar auto-computes disabled and selected images. */
1075 idx = TAB_BAR_IMAGE_ENABLED_SELECTED;
1076 eassert (ASIZE (image) >= idx);
1077 image = AREF (image, idx);
1078 }
1079 else
1080 {
1081 idx = -1;
1082 }
1083 helpObj = TABPROP (TAB_BAR_ITEM_HELP);
1084 if (NILP (helpObj))
1085 helpObj = TABPROP (TAB_BAR_ITEM_CAPTION);
1086 helpText = NILP (helpObj) ? "" : SSDATA (helpObj);
1087
1088 /* Ignore invalid image specifications. */
1089 if (!valid_image_p (image))
1090 {
1091 /* Don't log anything, GNUS makes invalid images all the time. */
1092 continue;
1093 }
1094
1095 img_id = lookup_image (f, image);
1096 img = IMAGE_FROM_ID (f, img_id);
1097 prepare_image_for_display (f, img);
1098
1099 if (img->load_failed_p || img->pixmap == nil)
1100 {
1101 NSLog (@"Could not prepare tabbar image for display.");
1102 continue;
1103 }
1104
1105 [tabbar addDisplayItemWithImage: img->pixmap
1106 idx: k++
1107 tag: i
1108 helpText: helpText
1109 enabled: enabled_p];
1110#undef TABPROP
1111 }
1112
1113 if (![tabbar isVisible])
1114 {
1115 f->output_data.ns->in_animation = 1;
1116 [tabbar setVisible: YES];
1117 f->output_data.ns->in_animation = 0;
1118 }
1119
1120#ifdef NS_IMPL_COCOA
1121 if ([tabbar changed])
1122 {
1123 /* Inform app that tabbar has changed. */
1124 NSDictionary *dict = [tabbar configurationDictionary];
1125 NSMutableDictionary *newDict = [dict mutableCopy];
1126 NSEnumerator *keys = [[dict allKeys] objectEnumerator];
1127 id key;
1128 while ((key = [keys nextObject]) != nil)
1129 {
1130 NSObject *val = [dict objectForKey: key];
1131 if ([val isKindOfClass: [NSArray class]])
1132 {
1133 [newDict setObject:
1134 [tabbar tabbarDefaultItemIdentifiers: tabbar]
1135 forKey: key];
1136 break;
1137 }
1138 }
1139 [tabbar setConfigurationFromDictionary: newDict];
1140 [newDict release];
1141 }
1142#endif
1143
1144 if (oldh != FRAME_TABBAR_HEIGHT (f))
1145 [view updateFrameSize:YES];
1146 if (view->wait_for_tab_bar && FRAME_TABBAR_HEIGHT (f) > 0)
1147 {
1148 view->wait_for_tab_bar = NO;
1149 [view setNeedsDisplay: YES];
1150 }
1151
1152 unblock_input ();
1153}
1154
1155
1156/* ==========================================================================
1157
1158 Tabbar: class implementation
1159
1160 ========================================================================== */
1161
1162@implementation EmacsTabbar
1163
1164- (instancetype)initForView: (EmacsView *)view withIdentifier: (NSString *)identifier
1165{
1166 NSTRACE ("[EmacsTabbar initForView: withIdentifier:]");
1167
1168 self = [super initWithIdentifier: identifier];
1169 emacsView = view;
1170 [self setDisplayMode: NSTabbarDisplayModeIconOnly];
1171 [self setSizeMode: NSTabbarSizeModeSmall];
1172 [self setDelegate: self];
1173 identifierToItem = [[NSMutableDictionary alloc] initWithCapacity: 10];
1174 activeIdentifiers = [[NSMutableArray alloc] initWithCapacity: 8];
1175 prevIdentifiers = nil;
1176 prevEnablement = enablement = 0L;
1177 return self;
1178}
1179
1180- (void)dealloc
1181{
1182 NSTRACE ("[EmacsTabbar dealloc]");
1183
1184 [prevIdentifiers release];
1185 [activeIdentifiers release];
1186 [identifierToItem release];
1187 [super dealloc];
1188}
1189
1190- (void) clearActive
1191{
1192 NSTRACE ("[EmacsTabbar clearActive]");
1193
1194 [prevIdentifiers release];
1195 prevIdentifiers = [activeIdentifiers copy];
1196 [activeIdentifiers removeAllObjects];
1197 prevEnablement = enablement;
1198 enablement = 0L;
1199}
1200
1201- (void) clearAll
1202{
1203 NSTRACE ("[EmacsTabbar clearAll]");
1204
1205 [self clearActive];
1206 while ([[self items] count] > 0)
1207 [self removeItemAtIndex: 0];
1208}
1209
1210- (BOOL) changed
1211{
1212 NSTRACE ("[EmacsTabbar changed]");
1213
1214 return [activeIdentifiers isEqualToArray: prevIdentifiers] &&
1215 enablement == prevEnablement ? NO : YES;
1216}
1217
1218- (void) addDisplayItemWithImage: (EmacsImage *)img
1219 idx: (int)idx
1220 tag: (int)tag
1221 helpText: (const char *)help
1222 enabled: (BOOL)enabled
1223{
1224 NSTRACE ("[EmacsTabbar addDisplayItemWithImage: ...]");
1225
1226 /* 1) come up w/identifier */
1227 NSString *identifier
1228 = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]];
1229 [activeIdentifiers addObject: identifier];
1230
1231 /* 2) create / reuse item */
1232 NSTabbarItem *item = [identifierToItem objectForKey: identifier];
1233 if (item == nil)
1234 {
1235 item = [[[NSTabbarItem alloc] initWithItemIdentifier: identifier]
1236 autorelease];
1237 [item setImage: img];
1238 [item setTabTip: [NSString stringWithUTF8String: help]];
1239 [item setTarget: emacsView];
1240 [item setAction: @selector (tabbarClicked:)];
1241 [identifierToItem setObject: item forKey: identifier];
1242 }
1243
1244#ifdef NS_IMPL_GNUSTEP
1245 [self insertItemWithItemIdentifier: identifier atIndex: idx];
1246#endif
1247
1248 [item setTag: tag];
1249 [item setEnabled: enabled];
1250
1251 /* 3) update state */
1252 enablement = (enablement << 1) | (enabled == YES);
1253}
1254
1255/* This overrides super's implementation, which automatically sets
1256 all items to enabled state (for some reason). */
1257- (void)validateVisibleItems
1258{
1259 NSTRACE ("[EmacsTabbar validateVisibleItems]");
1260}
1261
1262
1263/* delegate methods */
1264
1265- (NSTabbarItem *)tabbar: (NSTabbar *)tabbar
1266 itemForItemIdentifier: (NSString *)itemIdentifier
1267 willBeInsertedIntoTabbar: (BOOL)flag
1268{
1269 NSTRACE ("[EmacsTabbar tabbar: ...]");
1270
1271 /* Look up NSTabbarItem by identifier and return... */
1272 return [identifierToItem objectForKey: itemIdentifier];
1273}
1274
1275- (NSArray *)tabbarDefaultItemIdentifiers: (NSTabbar *)tabbar
1276{
1277 NSTRACE ("[EmacsTabbar tabbarDefaultItemIdentifiers:]");
1278
1279 /* Return entire set. */
1280 return activeIdentifiers;
1281}
1282
1283/* for configuration palette (not yet supported) */
1284- (NSArray *)tabbarAllowedItemIdentifiers: (NSTabbar *)tabbar
1285{
1286 NSTRACE ("[EmacsTabbar tabbarAllowedItemIdentifiers:]");
1287
1288 /* return entire set... */
1289 return activeIdentifiers;
1290 //return [identifierToItem allKeys];
1291}
1292
1293- (void)setVisible:(BOOL)shown
1294{
1295 NSTRACE ("[EmacsTabbar setVisible:%d]", shown);
1296
1297 [super setVisible:shown];
1298}
1299
1300
1301/* optional and unneeded */
1302/* - tabbarWillAddItem: (NSNotification *)notification { } */
1303/* - tabbarDidRemoveItem: (NSNotification *)notification { } */
1304/* - (NSArray *)tabbarSelectableItemIdentifiers: (NSTabbar *)tabbar */
1305
1306@end /* EmacsTabbar */
1307
1308
1309
1310/* ==========================================================================
1311
996 Toolbar: externally-called functions 1312 Toolbar: externally-called functions
997 1313
998 ========================================================================== */ 1314 ========================================================================== */