1/* 2 * tkMacOSXEvent.c -- 3 * 4 * This file contains the basic Mac OS X Event handling routines. 5 * 6 * Copyright (c) 1995-1997 Sun Microsystems, Inc. 7 * Copyright 2001, Apple Computer, Inc. 8 * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net> 9 * 10 * See the file "license.terms" for information on usage and redistribution 11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 * 13 * RCS: @(#) $Id: tkMacOSXEvent.c,v 1.3.2.16 2007/11/09 06:26:55 das Exp $ 14 */ 15 16#include "tkMacOSXPrivate.h" 17#include "tkMacOSXEvent.h" 18#include "tkMacOSXDebug.h" 19 20 21/* 22 *---------------------------------------------------------------------- 23 * 24 * TkMacOSXFlushWindows -- 25 * 26 * This routine flushes all the Carbon windows of the application. It 27 * is called by XSync(). 28 * 29 * Results: 30 * None. 31 * 32 * Side effects: 33 * Flushes all Carbon windows 34 * 35 *---------------------------------------------------------------------- 36 */ 37 38MODULE_SCOPE void 39TkMacOSXFlushWindows(void) 40{ 41 WindowRef wRef = GetWindowList(); 42 43 while (wRef) { 44 TK_IF_MAC_OS_X_API (3, HIWindowFlush, 45 ChkErr(HIWindowFlush, wRef); 46 ) TK_ELSE_MAC_OS_X (3, 47 CGrafPtr portPtr = GetWindowPort(wRef); 48 49 if (QDIsPortBuffered(portPtr)) { 50 QDFlushPortBuffer(portPtr, NULL); 51 } 52 ) TK_ENDIF 53 wRef = GetNextWindow(wRef); 54 } 55} 56 57/* 58 *---------------------------------------------------------------------- 59 * 60 * TkMacOSXProcessEvent -- 61 * 62 * This dispatches a filtered Carbon event to the appropriate handler 63 * 64 * Note on MacEventStatus.stopProcessing: Please be conservative in the 65 * individual handlers and don't assume the event is fully handled 66 * unless you *really* need to ensure that other handlers don't see the 67 * event anymore. Some OS manager or library might be interested in 68 * events even after they are already handled on the Tk level. 69 * 70 * Results: 71 * 0 on success 72 * -1 on failure 73 * 74 * Side effects: 75 * Converts a Carbon event to a Tk event 76 * 77 *---------------------------------------------------------------------- 78 */ 79 80MODULE_SCOPE int 81TkMacOSXProcessEvent( 82 TkMacOSXEvent *eventPtr, 83 MacEventStatus *statusPtr) 84{ 85 switch (eventPtr->eClass) { 86 case kEventClassMouse: 87 TkMacOSXProcessMouseEvent(eventPtr, statusPtr); 88 break; 89 case kEventClassWindow: 90 TkMacOSXProcessWindowEvent(eventPtr, statusPtr); 91 break; 92 case kEventClassKeyboard: 93 TkMacOSXProcessKeyboardEvent(eventPtr, statusPtr); 94 break; 95 case kEventClassApplication: 96 TkMacOSXProcessApplicationEvent(eventPtr, statusPtr); 97 break; 98 case kEventClassAppearance: 99 TkMacOSXProcessAppearanceEvent(eventPtr, statusPtr); 100 break; 101 case kEventClassMenu: 102 TkMacOSXProcessMenuEvent(eventPtr, statusPtr); 103 break; 104 case kEventClassCommand: 105 TkMacOSXProcessCommandEvent(eventPtr, statusPtr); 106 break; 107 default: { 108 TkMacOSXDbgMsg("Unrecognised event: %s", 109 TkMacOSXCarbonEventToAscii(eventPtr->eventRef)); 110 break; 111 } 112 } 113 return 0; 114} 115 116/* 117 *---------------------------------------------------------------------- 118 * 119 * TkMacOSXProcessMenuEvent -- 120 * 121 * This routine processes the event in eventPtr, and 122 * generates the appropriate Tk events from it. 123 * 124 * Results: 125 * True if event(s) are generated - false otherwise. 126 * 127 * Side effects: 128 * Additional events may be place on the Tk event queue. 129 * 130 *---------------------------------------------------------------------- 131 */ 132 133MODULE_SCOPE int 134TkMacOSXProcessMenuEvent( 135 TkMacOSXEvent *eventPtr, 136 MacEventStatus *statusPtr) 137{ 138 int menuContext; 139 OSStatus err; 140 141 switch (eventPtr->eKind) { 142 case kEventMenuBeginTracking: 143 case kEventMenuEndTracking: 144 case kEventMenuOpening: 145 case kEventMenuTargetItem: 146 break; 147 default: 148 return 0; 149 break; 150 } 151 err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamMenuContext, 152 typeUInt32, NULL, sizeof(menuContext), NULL, &menuContext); 153 if (err == noErr && ((menuContext & kMenuContextMenuBarTracking) || 154 (menuContext & kMenuContextPopUpTracking))) { 155 switch (eventPtr->eKind) { 156 MenuRef menu; 157 158 case kEventMenuBeginTracking: 159 TkMacOSXClearMenubarActive(); 160 161 /* 162 * Handle -postcommand 163 */ 164 165 TkMacOSXPreprocessMenu(); 166 TkMacOSXTrackingLoop(1); 167 break; 168 case kEventMenuEndTracking: 169 TkMacOSXTrackingLoop(0); 170 break; 171 case kEventMenuOpening: 172 err = ChkErr(GetEventParameter, eventPtr->eventRef, 173 kEventParamDirectObject, typeMenuRef, NULL, 174 sizeof(menu), NULL, &menu); 175 if (err == noErr) { 176 TkMacOSXClearActiveMenu(menu); 177 return TkMacOSXGenerateParentMenuSelectEvent(menu); 178 } 179 break; 180 case kEventMenuTargetItem: 181 err = ChkErr(GetEventParameter, eventPtr->eventRef, 182 kEventParamDirectObject, typeMenuRef, NULL, 183 sizeof(menu), NULL, &menu); 184 if (err == noErr) { 185 MenuItemIndex index; 186 187 err = ChkErr(GetEventParameter, eventPtr->eventRef, 188 kEventParamMenuItemIndex, typeMenuItemIndex, NULL, 189 sizeof(index), NULL, &index); 190 if (err == noErr) { 191 return TkMacOSXGenerateMenuSelectEvent(menu, index); 192 } 193 } 194 break; 195 } 196 } 197 return 0; 198} 199 200/* 201 *---------------------------------------------------------------------- 202 * 203 * TkMacOSXProcessCommandEvent -- 204 * 205 * This routine processes the event in eventPtr, and 206 * generates the appropriate Tk events from it. 207 * 208 * Results: 209 * True if event(s) are generated - false otherwise. 210 * 211 * Side effects: 212 * Additional events may be place on the Tk event queue. 213 * 214 *---------------------------------------------------------------------- 215 */ 216 217MODULE_SCOPE int 218TkMacOSXProcessCommandEvent( 219 TkMacOSXEvent *eventPtr, 220 MacEventStatus * statusPtr) 221{ 222 HICommand command; 223 int menuContext; 224 OSStatus err; 225 226 switch (eventPtr->eKind) { 227 case kEventCommandProcess: 228 case kEventCommandUpdateStatus: 229 break; 230 default: 231 return 0; 232 break; 233 } 234 err = ChkErr(GetEventParameter, eventPtr->eventRef, 235 kEventParamDirectObject, typeHICommand, NULL, sizeof(command), 236 NULL, &command); 237 if (err == noErr && (command.attributes & kHICommandFromMenu)) { 238 if (eventPtr->eKind == kEventCommandProcess) { 239 err = ChkErr(GetEventParameter, eventPtr->eventRef, 240 kEventParamMenuContext, typeUInt32, NULL, 241 sizeof(menuContext), NULL, &menuContext); 242 if (err == noErr && (menuContext & kMenuContextMenuBar) && 243 (menuContext & kMenuContextMenuBarTracking)) { 244 TkMacOSXHandleMenuSelect(GetMenuID(command.menu.menuRef), 245 command.menu.menuItemIndex, 246 (GetCurrentEventKeyModifiers() & optionKey) != 0); 247 return 1; 248 } 249 } else { 250 Tcl_CmdInfo dummy; 251 if (command.commandID == kHICommandPreferences && eventPtr->interp) { 252 if (Tcl_GetCommandInfo(eventPtr->interp, 253 "::tk::mac::ShowPreferences", &dummy)) { 254 if (!IsMenuItemEnabled(command.menu.menuRef, 255 command.menu.menuItemIndex)) { 256 EnableMenuItem(command.menu.menuRef, 257 command.menu.menuItemIndex); 258 } 259 } else { 260 if (IsMenuItemEnabled(command.menu.menuRef, 261 command.menu.menuItemIndex)) { 262 DisableMenuItem(command.menu.menuRef, 263 command.menu.menuItemIndex); 264 } 265 } 266 statusPtr->stopProcessing = 1; 267 return 1; 268 } 269 } 270 } 271 return 0; 272} 273