summaryrefslogtreecommitdiff
path: root/src/video/cocoa/event.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/video/cocoa/event.mm')
-rw-r--r--src/video/cocoa/event.mm700
1 files changed, 700 insertions, 0 deletions
diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm
new file mode 100644
index 000000000..9151f4002
--- /dev/null
+++ b/src/video/cocoa/event.mm
@@ -0,0 +1,700 @@
+/* $Id$ */
+
+/******************************************************************************
+ * Cocoa video driver *
+ * Known things left to do: *
+ * Nothing at the moment. *
+ ******************************************************************************/
+
+#ifdef WITH_COCOA
+
+#import <Cocoa/Cocoa.h>
+#import <sys/time.h> /* gettimeofday */
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/**
+ * Important notice regarding all modifications!!!!!!!
+ * There are certain limitations because the file is objective C++.
+ * gdb has limitations.
+ * C++ and objective C code can't be joined in all cases (classes stuff).
+ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
+ */
+
+
+/* Defined in stdbool.h */
+#ifndef __cplusplus
+# ifndef __BEOS__
+# undef bool
+# undef false
+# undef true
+# endif
+#endif
+
+
+#include "../../stdafx.h"
+#include "../../openttd.h"
+#include "../../debug.h"
+#include "../../macros.h"
+#include "../../os/macosx/splash.h"
+#include "../../variables.h"
+#include "../../gfx.h"
+#include "cocoa_v.h"
+#include "cocoa_keys.h"
+#include "../../blitter/factory.hpp"
+#include "../../fileio.h"
+
+#undef Point
+#undef Rect
+
+/* Right Mouse Button Emulation enum */
+enum {
+ RMBE_COMMAND,
+ RMBE_CONTROL,
+ RMBE_OFF,
+};
+
+
+static bool _show_mouse = true;
+static unsigned int _current_mods;
+static bool _tab_is_down;
+static bool _emulating_right_button;
+#ifdef _DEBUG
+static uint32 _tEvent;
+#endif
+
+
+static uint32 GetTick()
+{
+ struct timeval tim;
+
+ gettimeofday(&tim, NULL);
+ return tim.tv_usec / 1000 + tim.tv_sec * 1000;
+}
+
+
+void QZ_ShowMouse()
+{
+ if (!_show_mouse) {
+ [ NSCursor unhide ];
+ _show_mouse = true;
+
+ // Hide the openttd cursor when leaving the window
+ if (_cocoa_subdriver != NULL)
+ UndrawMouseCursor();
+ _cursor.in_window = false;
+ }
+}
+
+void QZ_HideMouse()
+{
+ if (_show_mouse) {
+ /*
+ * Don't hide the cursor when compiling in debug mode.
+ * Note: Not hiding the cursor will cause artefacts around it in 8bpp fullscreen mode.
+ */
+#ifndef _DEBUG
+ [ NSCursor hide ];
+#endif
+ _show_mouse = false;
+
+ // Show the openttd cursor again
+ _cursor.in_window = true;
+ }
+}
+
+static void QZ_WarpCursor(int x, int y)
+{
+ NSPoint p;
+ CGPoint cgp;
+
+ assert(_cocoa_subdriver);
+
+ /* Only allow warping when in foreground */
+ if (![ NSApp isActive ]) return;
+
+ p = NSMakePoint(x, y);
+ cgp = _cocoa_subdriver->PrivateLocalToCG(&p);
+
+ /* this is the magic call that fixes cursor "freezing" after warp */
+ CGSetLocalEventsSuppressionInterval(0.0);
+ /* Do the actual warp */
+ CGWarpMouseCursorPosition(cgp);
+
+ /* Generate the mouse moved event */
+}
+
+
+static void QZ_CheckPaletteAnim()
+{
+ if (_pal_count_dirty != 0) {
+ Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
+
+ switch (blitter->UsePaletteAnimation()) {
+ case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
+ _cocoa_subdriver->UpdatePalette(_pal_first_dirty, _pal_count_dirty);
+ break;
+
+ case Blitter::PALETTE_ANIMATION_BLITTER:
+ blitter->PaletteAnimate(_pal_first_dirty, _pal_count_dirty);
+ break;
+
+ case Blitter::PALETTE_ANIMATION_NONE:
+ break;
+
+ default:
+ NOT_REACHED();
+ }
+ _pal_count_dirty = 0;
+ }
+}
+
+
+
+struct VkMapping {
+ unsigned short vk_from;
+ byte map_to;
+};
+
+#define AS(x, z) {x, z}
+
+static const VkMapping _vk_mapping[] = {
+ AS(QZ_BACKQUOTE, WKC_BACKQUOTE), // key left of '1'
+ AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode
+
+ /* Pageup stuff + up/down */
+ AS(QZ_PAGEUP, WKC_PAGEUP),
+ AS(QZ_PAGEDOWN, WKC_PAGEDOWN),
+
+ AS(QZ_UP, WKC_UP),
+ AS(QZ_DOWN, WKC_DOWN),
+ AS(QZ_LEFT, WKC_LEFT),
+ AS(QZ_RIGHT, WKC_RIGHT),
+
+ AS(QZ_HOME, WKC_HOME),
+ AS(QZ_END, WKC_END),
+
+ AS(QZ_INSERT, WKC_INSERT),
+ AS(QZ_DELETE, WKC_DELETE),
+
+ /* Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) */
+ AS(QZ_a, 'A'),
+ AS(QZ_b, 'B'),
+ AS(QZ_c, 'C'),
+ AS(QZ_d, 'D'),
+ AS(QZ_e, 'E'),
+ AS(QZ_f, 'F'),
+ AS(QZ_g, 'G'),
+ AS(QZ_h, 'H'),
+ AS(QZ_i, 'I'),
+ AS(QZ_j, 'J'),
+ AS(QZ_k, 'K'),
+ AS(QZ_l, 'L'),
+ AS(QZ_m, 'M'),
+ AS(QZ_n, 'N'),
+ AS(QZ_o, 'O'),
+ AS(QZ_p, 'P'),
+ AS(QZ_q, 'Q'),
+ AS(QZ_r, 'R'),
+ AS(QZ_s, 'S'),
+ AS(QZ_t, 'T'),
+ AS(QZ_u, 'U'),
+ AS(QZ_v, 'V'),
+ AS(QZ_w, 'W'),
+ AS(QZ_x, 'X'),
+ AS(QZ_y, 'Y'),
+ AS(QZ_z, 'Z'),
+ /* Same thing for digits */
+ AS(QZ_0, '0'),
+ AS(QZ_1, '1'),
+ AS(QZ_2, '2'),
+ AS(QZ_3, '3'),
+ AS(QZ_4, '4'),
+ AS(QZ_5, '5'),
+ AS(QZ_6, '6'),
+ AS(QZ_7, '7'),
+ AS(QZ_8, '8'),
+ AS(QZ_9, '9'),
+
+ AS(QZ_ESCAPE, WKC_ESC),
+ AS(QZ_PAUSE, WKC_PAUSE),
+ AS(QZ_BACKSPACE, WKC_BACKSPACE),
+
+ AS(QZ_SPACE, WKC_SPACE),
+ AS(QZ_RETURN, WKC_RETURN),
+ AS(QZ_TAB, WKC_TAB),
+
+ /* Function keys */
+ AS(QZ_F1, WKC_F1),
+ AS(QZ_F2, WKC_F2),
+ AS(QZ_F3, WKC_F3),
+ AS(QZ_F4, WKC_F4),
+ AS(QZ_F5, WKC_F5),
+ AS(QZ_F6, WKC_F6),
+ AS(QZ_F7, WKC_F7),
+ AS(QZ_F8, WKC_F8),
+ AS(QZ_F9, WKC_F9),
+ AS(QZ_F10, WKC_F10),
+ AS(QZ_F11, WKC_F11),
+ AS(QZ_F12, WKC_F12),
+
+ /* Numeric part */
+ AS(QZ_KP0, WKC_NUM_0),
+ AS(QZ_KP1, WKC_NUM_1),
+ AS(QZ_KP2, WKC_NUM_2),
+ AS(QZ_KP3, WKC_NUM_3),
+ AS(QZ_KP4, WKC_NUM_4),
+ AS(QZ_KP5, WKC_NUM_5),
+ AS(QZ_KP6, WKC_NUM_6),
+ AS(QZ_KP7, WKC_NUM_7),
+ AS(QZ_KP8, WKC_NUM_8),
+ AS(QZ_KP9, WKC_NUM_9),
+ AS(QZ_KP_DIVIDE, WKC_NUM_DIV),
+ AS(QZ_KP_MULTIPLY, WKC_NUM_MUL),
+ AS(QZ_KP_MINUS, WKC_NUM_MINUS),
+ AS(QZ_KP_PLUS, WKC_NUM_PLUS),
+ AS(QZ_KP_ENTER, WKC_NUM_ENTER),
+ AS(QZ_KP_PERIOD, WKC_NUM_DECIMAL),
+
+ /* Other non-letter keys */
+ AS(QZ_SLASH, WKC_SLASH),
+ AS(QZ_SEMICOLON, WKC_SEMICOLON),
+ AS(QZ_EQUALS, WKC_EQUALS),
+ AS(QZ_LEFTBRACKET, WKC_L_BRACKET),
+ AS(QZ_BACKSLASH, WKC_BACKSLASH),
+ AS(QZ_RIGHTBRACKET, WKC_R_BRACKET),
+
+ AS(QZ_QUOTE, WKC_SINGLEQUOTE),
+ AS(QZ_COMMA, WKC_COMMA),
+ AS(QZ_MINUS, WKC_MINUS),
+ AS(QZ_PERIOD, WKC_PERIOD)
+};
+
+
+static uint32 QZ_MapKey(unsigned short sym)
+{
+ const VkMapping *map;
+ uint32 key = 0;
+
+ for (map = _vk_mapping; map != endof(_vk_mapping); ++map) {
+ if (sym == map->vk_from) {
+ key = map->map_to;
+ break;
+ }
+ }
+
+ if (_current_mods & NSShiftKeyMask) key |= WKC_SHIFT;
+ if (_current_mods & NSControlKeyMask) key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META);
+ if (_current_mods & NSAlternateKeyMask) key |= WKC_ALT;
+ if (_current_mods & NSCommandKeyMask) key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL);
+
+ return key << 16;
+}
+
+static void QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL down)
+{
+ switch (keycode) {
+ case QZ_UP: SB(_dirkeys, 1, 1, down); break;
+ case QZ_DOWN: SB(_dirkeys, 3, 1, down); break;
+ case QZ_LEFT: SB(_dirkeys, 0, 1, down); break;
+ case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break;
+
+ case QZ_TAB: _tab_is_down = down; break;
+
+ case QZ_RETURN:
+ case QZ_f:
+ if (down && (_current_mods & NSCommandKeyMask)) {
+ _video_driver->ToggleFullscreen(!_fullscreen);
+ }
+ break;
+ }
+
+ if (down) {
+ uint32 pressed_key = QZ_MapKey(keycode) | unicode;
+ HandleKeypress(pressed_key);
+ DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key);
+ } else {
+ DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode);
+ }
+}
+
+static void QZ_DoUnsidedModifiers(unsigned int newMods)
+{
+ const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA };
+
+ int i;
+ unsigned int bit;
+
+ if (_current_mods == newMods) return;
+
+ /* Iterate through the bits, testing each against the current modifiers */
+ for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
+ unsigned int currentMask, newMask;
+
+ currentMask = _current_mods & bit;
+ newMask = newMods & bit;
+
+ if (currentMask && currentMask != newMask) { /* modifier up event */
+ /* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
+ if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, YES);
+ QZ_KeyEvent(mapping[i], 0, NO);
+ } else if (newMask && currentMask != newMask) { /* modifier down event */
+ QZ_KeyEvent(mapping[i], 0, YES);
+ /* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
+ if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, NO);
+ }
+ }
+
+ _current_mods = newMods;
+}
+
+static void QZ_MouseMovedEvent(int x, int y)
+{
+ if (_cursor.fix_at) {
+ int dx = x - _cursor.pos.x;
+ int dy = y - _cursor.pos.y;
+
+ if (dx != 0 || dy != 0) {
+ _cursor.delta.x += dx;
+ _cursor.delta.y += dy;
+
+ QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y);
+ }
+ } else {
+ _cursor.delta.x = x - _cursor.pos.x;
+ _cursor.delta.y = y - _cursor.pos.y;
+ _cursor.pos.x = x;
+ _cursor.pos.y = y;
+ _cursor.dirty = true;
+ }
+ HandleMouseEvents();
+}
+
+
+static void QZ_MouseButtonEvent(int button, BOOL down)
+{
+ switch (button) {
+ case 0:
+ if (down) {
+ _left_button_down = true;
+ } else {
+ _left_button_down = false;
+ _left_button_clicked = false;
+ }
+ HandleMouseEvents();
+ break;
+
+ case 1:
+ if (down) {
+ _right_button_down = true;
+ _right_button_clicked = true;
+ } else {
+ _right_button_down = false;
+ }
+ HandleMouseEvents();
+ break;
+ }
+}
+
+
+
+
+static bool QZ_PollEvent()
+{
+ NSEvent *event;
+ NSPoint pt;
+ NSString *chars;
+#ifdef _DEBUG
+ uint32 et0, et;
+#endif
+
+ assert(_cocoa_subdriver != NULL);
+
+#ifdef _DEBUG
+ et0 = GetTick();
+#endif
+ event = [ NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate: [ NSDate distantPast ]
+ inMode: NSDefaultRunLoopMode dequeue:YES ];
+#ifdef _DEBUG
+ et = GetTick();
+ _tEvent+= et - et0;
+#endif
+
+ if (event == nil) return false;
+ if (!_cocoa_subdriver->IsActive()) {
+ QZ_ShowMouse();
+ [NSApp sendEvent:event];
+ return true;
+ }
+
+ QZ_DoUnsidedModifiers( [ event modifierFlags ] );
+
+ switch ([event type]) {
+ case NSMouseMoved:
+ case NSOtherMouseDragged:
+ case NSRightMouseDragged:
+ case NSLeftMouseDragged:
+ pt = _cocoa_subdriver->GetMouseLocation(event);
+ if (!_cocoa_subdriver->MouseIsInsideView(&pt) &&
+ !_emulating_right_button) {
+ QZ_ShowMouse();
+ [NSApp sendEvent:event];
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+ break;
+
+ case NSLeftMouseDown:
+ {
+ uint32 keymask = 0;
+ if (_patches.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask;
+ if (_patches.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask;
+
+ pt = _cocoa_subdriver->GetMouseLocation(event);
+
+ if (!([ event modifierFlags ] & keymask) ||
+ !_cocoa_subdriver->MouseIsInsideView(&pt)) {
+ [NSApp sendEvent:event];
+ }
+
+ if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+ QZ_ShowMouse();
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+
+ /* Right mouse button emulation */
+ if ([ event modifierFlags ] & keymask) {
+ _emulating_right_button = true;
+ QZ_MouseButtonEvent(1, YES);
+ } else {
+ QZ_MouseButtonEvent(0, YES);
+ }
+ break;
+ }
+ case NSLeftMouseUp:
+ [NSApp sendEvent:event];
+
+ pt = _cocoa_subdriver->GetMouseLocation(event);
+ if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+ QZ_ShowMouse();
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+
+ /* Right mouse button emulation */
+ if (_emulating_right_button) {
+ _emulating_right_button = false;
+ QZ_MouseButtonEvent(1, NO);
+ } else {
+ QZ_MouseButtonEvent(0, NO);
+ }
+ break;
+
+ case NSRightMouseDown:
+ pt = _cocoa_subdriver->GetMouseLocation(event);
+ if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+ QZ_ShowMouse();
+ [NSApp sendEvent:event];
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+ QZ_MouseButtonEvent(1, YES);
+ break;
+
+ case NSRightMouseUp:
+ pt = _cocoa_subdriver->GetMouseLocation(event);
+ if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
+ QZ_ShowMouse();
+ [NSApp sendEvent:event];
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+ QZ_MouseButtonEvent(1, NO);
+ break;
+
+#if 0
+ /* This is not needed since openttd currently only use two buttons */
+ case NSOtherMouseDown:
+ pt = QZ_GetMouseLocation(event);
+ if (!QZ_MouseIsInsideView(&pt)) {
+ QZ_ShowMouse();
+ [NSApp sendEvent:event];
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+ QZ_MouseButtonEvent([ event buttonNumber ], YES);
+ break;
+
+ case NSOtherMouseUp:
+ pt = QZ_GetMouseLocation(event);
+ if (!QZ_MouseIsInsideView(&pt)) {
+ QZ_ShowMouse();
+ [NSApp sendEvent:event];
+ break;
+ }
+
+ QZ_HideMouse();
+ QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
+ QZ_MouseButtonEvent([ event buttonNumber ], NO);
+ break;
+#endif
+
+ case NSKeyDown:
+ /* Quit, hide and minimize */
+ switch ([event keyCode]) {
+ case QZ_q:
+ case QZ_h:
+ case QZ_m:
+ if ([ event modifierFlags ] & NSCommandKeyMask) {
+ [NSApp sendEvent:event];
+ }
+ break;
+ }
+
+ chars = [ event characters ];
+ QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, YES);
+ break;
+
+ case NSKeyUp:
+ /* Quit, hide and minimize */
+ switch ([event keyCode]) {
+ case QZ_q:
+ case QZ_h:
+ case QZ_m:
+ if ([ event modifierFlags ] & NSCommandKeyMask) {
+ [NSApp sendEvent:event];
+ }
+ break;
+ }
+
+ chars = [ event characters ];
+ QZ_KeyEvent([event keyCode], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO);
+ break;
+
+ case NSScrollWheel:
+ if ([ event deltaY ] > 0.0) { /* Scroll up */
+ _cursor.wheel--;
+ } else if ([ event deltaY ] < 0.0) { /* Scroll down */
+ _cursor.wheel++;
+ } /* else: deltaY was 0.0 and we don't want to do anything */
+
+ /* Set the scroll count for scrollwheel scrolling */
+ _cursor.h_wheel -= (int)([ event deltaX ]* 5 * _patches.scrollwheel_multiplier);
+ _cursor.v_wheel -= (int)([ event deltaY ]* 5 * _patches.scrollwheel_multiplier);
+ break;
+
+ default:
+ [NSApp sendEvent:event];
+ }
+
+ return true;
+}
+
+
+void QZ_GameLoop()
+{
+ uint32 cur_ticks = GetTick();
+ uint32 last_cur_ticks = cur_ticks;
+ uint32 next_tick = cur_ticks + 30;
+ uint32 pal_tick = 0;
+#ifdef _DEBUG
+ uint32 et0, et, st0, st;
+#endif
+ int i;
+
+#ifdef _DEBUG
+ et0 = GetTick();
+ st = 0;
+#endif
+
+ _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+ DisplaySplashImage();
+ QZ_CheckPaletteAnim();
+ _cocoa_subdriver->Draw();
+ CSleep(1);
+
+ for (i = 0; i < 2; i++) GameLoop();
+
+ _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+ UpdateWindows();
+ QZ_CheckPaletteAnim();
+ _cocoa_subdriver->Draw();
+ CSleep(1);
+
+ for (;;) {
+ uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
+ InteractiveRandom(); // randomness
+
+ while (QZ_PollEvent()) {}
+
+ if (_exit_game) break;
+
+#if defined(_DEBUG)
+ if (_current_mods & NSShiftKeyMask)
+#else
+ if (_tab_is_down)
+#endif
+ {
+ if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
+ } else if (_fast_forward & 2) {
+ _fast_forward = 0;
+ }
+
+ cur_ticks = GetTick();
+ if (cur_ticks >= next_tick || (_fast_forward && !_pause_game) || cur_ticks < prev_cur_ticks) {
+ _realtime_tick += cur_ticks - last_cur_ticks;
+ last_cur_ticks = cur_ticks;
+ next_tick = cur_ticks + 30;
+
+ _ctrl_pressed = !!(_current_mods & ( _patches.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask));
+ _shift_pressed = !!(_current_mods & NSShiftKeyMask);
+
+ GameLoop();
+
+ _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+ UpdateWindows();
+ if (++pal_tick > 4) {
+ QZ_CheckPaletteAnim();
+ pal_tick = 1;
+ }
+ _cocoa_subdriver->Draw();
+ } else {
+#ifdef _DEBUG
+ st0 = GetTick();
+#endif
+ CSleep(1);
+#ifdef _DEBUG
+ st += GetTick() - st0;
+#endif
+ _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer();
+ DrawChatMessage();
+ DrawMouseCursor();
+ _cocoa_subdriver->Draw();
+ }
+ }
+
+#ifdef _DEBUG
+ et = GetTick();
+
+ DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _tEvent);
+ DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st);
+ DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_tEvent / (double)(et - et0) * 100);
+ DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_tEvent / (double)(et - et0 - st) * 100);
+#endif
+}
+
+#endif /* WITH_COCOA */