1# ---------------------------------------------------------------------------- 2# pyglet 3# Copyright (c) 2006-2008 Alex Holkner 4# Copyright (c) 2008-2020 pyglet contributors 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 11# * Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# * Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in 15# the documentation and/or other materials provided with the 16# distribution. 17# * Neither the name of pyglet nor the names of its 18# contributors may be used to endorse or promote products 19# derived from this software without specific prior written 20# permission. 21# 22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33# POSSIBILITY OF SUCH DAMAGE. 34# ---------------------------------------------------------------------------- 35 36from pyglet.libs.darwin.cocoapy import ObjCClass, ObjCSubclass, ObjCInstance 37from pyglet.libs.darwin.cocoapy import NSApplicationDidHideNotification 38from pyglet.libs.darwin.cocoapy import NSApplicationDidUnhideNotification 39from pyglet.libs.darwin.cocoapy import send_super, get_selector 40from pyglet.libs.darwin.cocoapy import PyObjectEncoding 41from pyglet.libs.darwin.cocoapy import quartz 42from .systemcursor import SystemCursor 43 44NSNotificationCenter = ObjCClass('NSNotificationCenter') 45NSApplication = ObjCClass('NSApplication') 46 47 48class PygletDelegate_Implementation: 49 PygletDelegate = ObjCSubclass('NSObject', 'PygletDelegate') 50 51 @PygletDelegate.method(b'@'+PyObjectEncoding) 52 def initWithWindow_(self, window): 53 self = ObjCInstance(send_super(self, 'init')) 54 55 if not self: 56 return None 57 58 # CocoaWindow object. 59 self._window = window 60 window._nswindow.setDelegate_(self) 61 62 # Register delegate for hide and unhide notifications so that we 63 # can dispatch the corresponding pyglet events. 64 notificationCenter = NSNotificationCenter.defaultCenter() 65 66 notificationCenter.addObserver_selector_name_object_( 67 self, get_selector('applicationDidHide:'), 68 NSApplicationDidHideNotification, None) 69 70 notificationCenter.addObserver_selector_name_object_( 71 self, get_selector('applicationDidUnhide:'), 72 NSApplicationDidUnhideNotification, None) 73 74 # Flag set when we pause exclusive mouse mode if window loses key status. 75 self.did_pause_exclusive_mouse = False 76 return self 77 78 @PygletDelegate.method('v') 79 def dealloc(self): 80 # Unregister delegate from notification center. 81 notificationCenter = NSNotificationCenter.defaultCenter() 82 notificationCenter.removeObserver_(self) 83 self._window = None 84 send_super(self, 'dealloc') 85 86 @PygletDelegate.method('v@') 87 def applicationDidHide_(self, notification): 88 self._window.dispatch_event("on_hide") 89 90 @PygletDelegate.method('v@') 91 def applicationDidUnhide_(self, notification): 92 if self._window._is_mouse_exclusive and quartz.CGCursorIsVisible(): 93 # The cursor should be hidden, but for some reason it's not; 94 # try to force the cursor to hide (without over-hiding). 95 SystemCursor.unhide() 96 SystemCursor.hide() 97 pass 98 self._window.dispatch_event("on_show") 99 100 @PygletDelegate.method('B@') 101 def windowShouldClose_(self, notification): 102 # The method is not called if [NSWindow close] was used. 103 self._window.dispatch_event("on_close") 104 return False 105 106 @PygletDelegate.method('v@') 107 def windowDidMove_(self, notification): 108 x, y = self._window.get_location() 109 self._window.dispatch_event("on_move", x, y) 110 111 @PygletDelegate.method('v@') 112 def windowDidBecomeKey_(self, notification): 113 # Restore exclusive mouse mode if it was active before we lost key status. 114 if self.did_pause_exclusive_mouse: 115 self._window.set_exclusive_mouse(True) 116 self.did_pause_exclusive_mouse = False 117 self._window._nswindow.setMovable_(True) # Mac OS 10.6 118 # Restore previous mouse visibility settings. 119 self._window.set_mouse_platform_visible() 120 self._window.dispatch_event("on_activate") 121 122 @PygletDelegate.method('v@') 123 def windowDidResignKey_(self, notification): 124 # Pause exclusive mouse mode if it is active. 125 if self._window._is_mouse_exclusive: 126 self._window.set_exclusive_mouse(False) 127 self.did_pause_exclusive_mouse = True 128 # We need to prevent the window from being unintentionally dragged 129 # (by the call to set_mouse_position in set_exclusive_mouse) when 130 # the window is reactivated by clicking on its title bar. 131 self._window._nswindow.setMovable_(False) # Mac OS X 10.6 132 # Make sure that cursor is visible. 133 self._window.set_mouse_platform_visible(True) 134 self._window.dispatch_event("on_deactivate") 135 136 @PygletDelegate.method('v@') 137 def windowDidMiniaturize_(self, notification): 138 self._window.dispatch_event("on_hide") 139 140 @PygletDelegate.method('v@') 141 def windowDidDeminiaturize_(self, notification): 142 if self._window._is_mouse_exclusive and quartz.CGCursorIsVisible(): 143 # The cursor should be hidden, but for some reason it's not; 144 # try to force the cursor to hide (without over-hiding). 145 SystemCursor.unhide() 146 SystemCursor.hide() 147 pass 148 self._window.dispatch_event("on_show") 149 150 @PygletDelegate.method('v@') 151 def windowDidExpose_(self, notification): 152 self._window.dispatch_event("on_expose") 153 154 @PygletDelegate.method('v@') 155 def terminate_(self, sender): 156 NSApp = NSApplication.sharedApplication() 157 NSApp.terminate_(self) 158 159 @PygletDelegate.method('B@') 160 def validateMenuItem_(self, menuitem): 161 # Disable quitting with command-q when in keyboard exclusive mode. 162 if menuitem.action() == get_selector('terminate:'): 163 return not self._window._is_keyboard_exclusive 164 return True 165 166 167PygletDelegate = ObjCClass('PygletDelegate') 168