author | Claus Gittinger <cg@exept.de> |
Fri, 17 Feb 2017 10:25:31 +0100 | |
changeset 21480 | 20b4ddb4ba7a |
parent 21455 | a657a28cab85 |
child 21580 | b0c093983502 |
permissions | -rw-r--r-- |
21452 | 1 |
" |
2 |
COPYRIGHT (c) 2013 by Claus Gittinger |
|
21455 | 3 |
All Rights Reserved |
21452 | 4 |
|
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
17471 | 12 |
"{ Package: 'stx:libbasic' }" |
13 |
||
14 |
"{ NameSpace: Smalltalk }" |
|
14819 | 15 |
|
17471 | 16 |
UnixOperatingSystem subclass:#OSXOperatingSystem |
17 |
instanceVariableNames:'' |
|
18 |
classVariableNames:'' |
|
19 |
poolDictionaries:'' |
|
20 |
category:'OS-Unix' |
|
21 |
! |
|
22 |
||
21452 | 23 |
!OSXOperatingSystem primitiveDefinitions! |
24 |
%{ |
|
25 |
||
26 |
#ifndef __OSX__ |
|
27 |
# define NO_QUARTZ |
|
28 |
# define NO_COCOA |
|
29 |
#endif |
|
30 |
||
31 |
#ifndef NO_COCOA |
|
32 |
||
33 |
# undef Array |
|
34 |
# undef Number |
|
35 |
# undef Method |
|
36 |
# undef Point |
|
37 |
# undef Rectangle |
|
38 |
# undef Block |
|
39 |
# undef String |
|
40 |
# undef Character |
|
41 |
# undef Message |
|
42 |
# undef Object |
|
43 |
# undef Context |
|
44 |
# undef Time |
|
45 |
# undef Date |
|
46 |
# undef Set |
|
47 |
# undef Signal |
|
48 |
# undef Delay |
|
49 |
# undef NameSpace |
|
50 |
# undef Process |
|
51 |
# undef Processor |
|
52 |
# undef Class |
|
53 |
# undef FixedPoint |
|
54 |
# undef true |
|
55 |
# undef false |
|
56 |
||
57 |
# undef INT |
|
58 |
# undef UINT |
|
59 |
||
60 |
#include <ApplicationServices/ApplicationServices.h> |
|
61 |
#include <CoreFoundation/CoreFoundation.h> |
|
62 |
// #include <Foundation/Foundation.h> |
|
63 |
||
64 |
#include <stdlib.h> |
|
65 |
#include <stdio.h> |
|
66 |
#include <IOKit/graphics/IOGraphicsLib.h> |
|
67 |
||
68 |
#include <objc/runtime.h> |
|
69 |
#include <objc/message.h> |
|
70 |
||
71 |
# ifdef __DEF_Array |
|
72 |
# define Array __DEF_Array |
|
73 |
# endif |
|
74 |
# ifdef __DEF_Number |
|
75 |
# define Number __DEF_Number |
|
76 |
# endif |
|
77 |
# ifdef __DEF_Method |
|
78 |
# define Method __DEF_Method |
|
79 |
# endif |
|
80 |
# ifdef __DEF_Point |
|
81 |
# define Point __DEF_Point |
|
82 |
# endif |
|
83 |
# ifdef __DEF_Rectangle |
|
84 |
# define Rectangle __DEF_Rectangle |
|
85 |
# endif |
|
86 |
# ifdef __DEF_Block |
|
87 |
# define Block __DEF_Block |
|
88 |
# endif |
|
89 |
# ifdef __DEF_String |
|
90 |
# define String __DEF_String |
|
91 |
# endif |
|
92 |
# ifdef __DEF_Character |
|
93 |
# define Character __DEF_Character |
|
94 |
# endif |
|
95 |
# ifdef __DEF_Message |
|
96 |
# define Message __DEF_Message |
|
97 |
# endif |
|
98 |
# ifdef __DEF_Object |
|
99 |
# define Object __DEF_Object |
|
100 |
# endif |
|
101 |
# ifdef __DEF_Context |
|
102 |
# define Context __DEF_Context |
|
103 |
# endif |
|
104 |
# ifdef __DEF_Date |
|
105 |
# define Date __DEF_Date |
|
106 |
# endif |
|
107 |
# ifdef __DEF_Time |
|
108 |
# define Time __DEF_Time |
|
109 |
# endif |
|
110 |
# ifdef __DEF_Set |
|
111 |
# define Set __DEF_Set |
|
112 |
# endif |
|
113 |
# ifdef __DEF_Signal |
|
114 |
# define Signal __DEF_Signal |
|
115 |
# endif |
|
116 |
# ifdef __DEF_Delay |
|
117 |
# define Delay __DEF_Delay |
|
118 |
# endif |
|
119 |
# ifdef __DEF_NameSpace |
|
120 |
# define NameSpace __DEF_NameSpace |
|
121 |
# endif |
|
122 |
# ifdef __DEF_Process |
|
123 |
# define Process __DEF_Process |
|
124 |
# endif |
|
125 |
# ifdef __DEF_Processor |
|
126 |
# define Processor __DEF_Processor |
|
127 |
# endif |
|
128 |
# ifdef __DEF_Class |
|
129 |
# define Class __DEF_Class |
|
130 |
# endif |
|
131 |
# ifdef __DEF_FixedPoint |
|
132 |
# define FixedPoint __DEF_FixedPoint |
|
133 |
# endif |
|
134 |
# ifdef __DEF_true |
|
135 |
# undef true |
|
136 |
# define true __DEF_true |
|
137 |
# endif |
|
138 |
# ifdef __DEF_false |
|
139 |
# undef false |
|
140 |
# define false __DEF_false |
|
141 |
# endif |
|
142 |
||
143 |
# define INT STX_INT |
|
144 |
# define UINT STX_UINT |
|
145 |
||
146 |
#endif // NP_COCOA |
|
147 |
||
148 |
%} |
|
149 |
! ! |
|
150 |
||
151 |
!OSXOperatingSystem primitiveFunctions! |
|
152 |
%{ |
|
153 |
||
154 |
#ifndef NO_COCOA |
|
155 |
||
156 |
CGEventRef |
|
157 |
myCGEventCallback(CGEventTapProxy proxy, CGEventType type, |
|
158 |
CGEventRef event, void *refcon) |
|
159 |
{ |
|
160 |
// Paranoid sanity check. |
|
161 |
if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp)) |
|
162 |
return event; |
|
163 |
||
164 |
// The incoming keycode. |
|
165 |
CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); |
|
166 |
||
167 |
//Keypress code goes here. |
|
168 |
||
169 |
// We must return the event for it to be useful. |
|
170 |
return event; |
|
171 |
} |
|
172 |
||
173 |
#endif // NO_COCOA |
|
174 |
||
175 |
%} |
|
176 |
! ! |
|
177 |
||
178 |
!OSXOperatingSystem class methodsFor:'documentation'! |
|
179 |
||
180 |
copyright |
|
181 |
" |
|
182 |
COPYRIGHT (c) 2013 by Claus Gittinger |
|
21455 | 183 |
All Rights Reserved |
21452 | 184 |
|
185 |
This software is furnished under a license and may be used |
|
186 |
only in accordance with the terms of that license and with the |
|
187 |
inclusion of the above copyright notice. This software may not |
|
188 |
be provided or otherwise made available to, or used by, any |
|
189 |
other person. No title to or ownership of the software is |
|
190 |
hereby transferred. |
|
191 |
" |
|
192 |
! |
|
193 |
||
194 |
documentation |
|
195 |
" |
|
196 |
a small number of OS-X specific redefinitions here. |
|
197 |
||
198 |
[Author:] |
|
21455 | 199 |
Claus Gittinger |
21452 | 200 |
" |
201 |
! ! |
|
17471 | 202 |
|
203 |
!OSXOperatingSystem class methodsFor:'initialization'! |
|
204 |
||
205 |
initializeCodeset |
|
206 |
super initializeCodeset. |
|
17493 | 207 |
Codeset := #'utf8-mac'. |
17494 | 208 |
CodesetEncoder := nil. |
17471 | 209 |
! ! |
14819 | 210 |
|
21452 | 211 |
!OSXOperatingSystem class methodsFor:'cocoa - events'! |
212 |
||
213 |
receiveNextEvent |
|
214 |
%{ |
|
215 |
#ifndef NO_COCOA |
|
216 |
# if 0 |
|
217 |
CFMachPortRef eventTap; |
|
218 |
CGEventMask eventMask; |
|
219 |
CFRunLoopSourceRef runLoopSource; |
|
220 |
||
221 |
// Create an event tap. We are interested in key presses. |
|
222 |
eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp)); |
|
223 |
eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, |
|
224 |
eventMask, NULL, myCGEventCallback); |
|
225 |
if (!eventTap) { |
|
226 |
fprintf(stderr, "failed to create event tap\n"); |
|
227 |
} else{ |
|
228 |
fprintf(stderr, "ok\n"); |
|
229 |
} |
|
230 |
||
231 |
// Create a run loop source. |
|
232 |
runLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, eventTap, 0); |
|
233 |
# if 0 |
|
234 |
// Add to the current run loop. kCFRunLoopCommonModes); |
|
235 |
# endif |
|
236 |
// Enable the event tap. |
|
237 |
CGEventTapEnable(eventTap, true); |
|
238 |
||
239 |
# endif |
|
240 |
#endif // NO_COCOA |
|
241 |
%}. |
|
242 |
self primitiveFailed |
|
243 |
! ! |
|
244 |
||
17297
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
245 |
!OSXOperatingSystem class methodsFor:'dummy shell operations'! |
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
246 |
|
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
247 |
openApplicationHelperCommand |
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
248 |
"Return a command line helper to open a default application for file or URL" |
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
249 |
|
18279 | 250 |
(self canExecuteCommand: 'open') ifTrue:[ |
251 |
^ 'open' |
|
17297
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
252 |
]. |
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
253 |
^ nil |
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
254 |
|
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
255 |
"Created: / 13-01-2015 / 09:23:18 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
17427 | 256 |
! |
257 |
||
17428 | 258 |
openTerminalWithCommand:shellCommand inBackground:inBackground |
17427 | 259 |
"open a new terminal, which executes a command" |
260 |
||
17428 | 261 |
|cmd| |
262 |
||
263 |
cmd := 'osascript -e ''tell application "Terminal" to do script "%1"''' bindWith:shellCommand. |
|
264 |
||
265 |
inBackground ifTrue:[ |
|
18279 | 266 |
^ self |
267 |
startProcess:cmd |
|
268 |
inputFrom:nil |
|
269 |
outputTo:nil |
|
270 |
errorTo:nil |
|
271 |
auxFrom:nil |
|
272 |
environment:nil |
|
273 |
inDirectory:nil |
|
17428 | 274 |
] ifFalse:[ |
18279 | 275 |
^ self executeCommand:cmd |
17428 | 276 |
]. |
17427 | 277 |
|
278 |
" |
|
17428 | 279 |
OSXOperatingSystem openTerminalWithCommand:'ls -l' inBackground:true |
17427 | 280 |
" |
17297
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
281 |
! ! |
a56ba300949c
Overriden openApplicationForDocument... to use desktop-specific "open" command.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
17179
diff
changeset
|
282 |
|
14819 | 283 |
!OSXOperatingSystem class methodsFor:'file queries'! |
284 |
||
285 |
caseSensitiveFilenames |
|
286 |
"return true, if the OS has caseSensitive file naming. |
|
287 |
On MSDOS, this will return false; |
|
19817 | 288 |
on a real OS, we return true. |
289 |
Be aware, that OSX can be configured to be either. |
|
290 |
Also, that it actually depends on the mounted volume" |
|
14819 | 291 |
|
18279 | 292 |
"/ actually, this is wrong and depends on the mounted volume; |
293 |
"/ so we need a query for a particular directory (and/or volume). |
|
14819 | 294 |
^ false |
295 |
||
296 |
"Modified: / 5.6.1998 / 18:35:18 / cg" |
|
16381 | 297 |
! |
298 |
||
16644 | 299 |
defaultPackagePath |
20639 | 300 |
"redefined to add /Application and /Library stuff" |
20642 | 301 |
"called by Smalltalk initSystemPath" |
302 |
"self defaultPackagePath" |
|
16644 | 303 |
|
21452 | 304 |
|path executablePath executableDir packagesDir |
20637 | 305 |
libDir appDir versionsDir vsnDirName vsnDir| |
16644 | 306 |
|
307 |
path := super defaultPackagePath. |
|
308 |
||
309 |
executablePath := OperatingSystem pathOfSTXExecutable. |
|
310 |
executablePath notNil ifTrue:[ |
|
21452 | 311 |
executableDir := executablePath asFilename directory. |
312 |
packagesDir := executableDir directory directory / 'Packages'. |
|
313 |
packagesDir exists ifTrue:[ |
|
314 |
packagesDir := packagesDir pathName. |
|
315 |
(path includes:packagesDir) ifFalse:[ |
|
316 |
path add:packagesDir. |
|
317 |
]. |
|
318 |
]. |
|
319 |
libDir := '/Library/Frameworks/SmalltalkX.framework' asFilename. |
|
320 |
libDir exists ifTrue:[ |
|
321 |
versionsDir := libDir / 'Versions'. |
|
322 |
versionsDir exists ifTrue:[ |
|
323 |
vsnDirName := '%1.%2.%3' |
|
324 |
bindWith:Smalltalk majorVersionNr |
|
325 |
with:Smalltalk minorVersionNr |
|
326 |
with:Smalltalk revisionNr. |
|
327 |
vsnDir := versionsDir / vsnDirName. |
|
328 |
vsnDir exists ifTrue:[ |
|
329 |
vsnDir := vsnDir pathName. |
|
330 |
(path includes:vsnDir) ifFalse:[ |
|
331 |
path add:vsnDir. |
|
332 |
]. |
|
333 |
]. |
|
334 |
]. |
|
335 |
]. |
|
336 |
appDir := '/Applications/SmalltalkX/' asFilename. |
|
337 |
appDir exists ifTrue:[ |
|
338 |
versionsDir := appDir / 'Versions'. |
|
339 |
versionsDir exists ifTrue:[ |
|
340 |
vsnDirName := '%1.%2.%3' |
|
341 |
bindWith:Smalltalk majorVersionNr |
|
342 |
with:Smalltalk minorVersionNr |
|
343 |
with:Smalltalk revisionNr. |
|
344 |
vsnDir := versionsDir / vsnDirName. |
|
345 |
vsnDir exists ifTrue:[ |
|
346 |
vsnDir := vsnDir pathName. |
|
347 |
(path includes:vsnDir) ifFalse:[ |
|
348 |
path add:vsnDir. |
|
349 |
]. |
|
350 |
]. |
|
351 |
]. |
|
352 |
]. |
|
16644 | 353 |
]. |
16647 | 354 |
^ path |
16644 | 355 |
! |
356 |
||
16677 | 357 |
getDriveList |
358 |
"return a list of volumes in the system." |
|
359 |
||
360 |
^ ('/Volumes' asFilename directoryContents) |
|
361 |
, super getDriveList |
|
362 |
! |
|
363 |
||
16381 | 364 |
getTrashDirectory |
365 |
"get the name of a trash folder (if the OS supports it), |
|
366 |
or nil, if not. |
|
367 |
Must be redefined to return non nil in concrete operating systems" |
|
368 |
||
369 |
^ '~/.Trash' |
|
16677 | 370 |
! |
371 |
||
372 |
pathNameForDrive:driveName |
|
373 |
"given a drive name, return the pathname to open it as a directory. |
|
374 |
For Windows, this is the driveName itself. |
|
375 |
For OSX, '/Volumes' is prepended. |
|
376 |
Other OSs might prepent the pount point (i.e. /mnt/)" |
|
377 |
||
16905 | 378 |
driveName isNil ifTrue:[^ nil]. |
16677 | 379 |
driveName asFilename isAbsolute ifTrue:[^ driveName]. |
380 |
^ '/Volumes/',driveName |
|
17177 | 381 |
! |
382 |
||
383 |
supportsVolumes |
|
18279 | 384 |
"return true if the os support a list of drives/volumes |
17179 | 385 |
(here we can return a list of mounted drives in /Volumes)" |
17177 | 386 |
|
387 |
^ true |
|
14819 | 388 |
! ! |
389 |
||
21452 | 390 |
!OSXOperatingSystem class methodsFor:'quartz - screen'! |
391 |
||
392 |
getFrameBufferImage:displayNr |
|
393 |
"returns the framebuffer as an image object" |
|
394 |
||
395 |
|width height bytesPerPixel address pixels depth pad img| |
|
396 |
||
397 |
%{ |
|
398 |
#ifndef NO_QUARTZ |
|
399 |
CGImageRef image_ref = CGDisplayCreateImage(CGMainDisplayID()); |
|
400 |
CGDataProviderRef provider = CGImageGetDataProvider(image_ref); |
|
401 |
CFDataRef dataref = CGDataProviderCopyData(provider); |
|
402 |
size_t c_width, c_height; |
|
403 |
||
404 |
c_width = CGImageGetWidth(image_ref); |
|
405 |
c_height = CGImageGetHeight(image_ref); |
|
406 |
size_t c_bytesPerPixel = CGImageGetBitsPerPixel(image_ref) / 8; |
|
407 |
pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * c_bytesPerPixel); |
|
408 |
// uint8 *pixels = malloc(c_width * c_height * c_bytesPerPixel); |
|
409 |
memcpy(__byteArrayVal(pixels), CFDataGetBytePtr(dataref), c_width * c_height * c_bytesPerPixel); |
|
410 |
CFRelease(dataref); |
|
411 |
CGImageRelease(image_ref); |
|
412 |
||
413 |
width = __MKUINT( c_width ); |
|
414 |
height = __MKUINT( c_height ); |
|
415 |
bytesPerPixel = __MKUINT( c_bytesPerPixel ); |
|
416 |
||
417 |
// CGDisplayBaseAddress is deprecated |
|
418 |
// |
|
419 |
// int i, saveFD = -1; |
|
420 |
// uint32_t rowBytes, rowUInt32s, *screen; |
|
421 |
// |
|
422 |
// CGDirectDisplayID targetDisplay = 0; |
|
423 |
// |
|
424 |
// // populate targetDisplay as in Figure 10.23 |
|
425 |
// // use listDisplays() from Figure 10.23 |
|
426 |
// // ... |
|
427 |
// |
|
428 |
// screen = (uint32_t *)CGDisplayBaseAddress(targetDisplay); |
|
429 |
// rowBytes = CGDisplayBytesPerRow(targetDisplay); |
|
430 |
// rowUInt32s = rowBytes / 4; |
|
431 |
// width = __MKUINT( CGDisplayPixelsWide(targetDisplay) ); |
|
432 |
// height = __MKUINT( CGDisplayPixelsHigh(targetDisplay) ); |
|
433 |
||
434 |
// for (i = 0; i < height; i++) |
|
435 |
// write(saveFD, screen + i * rowUInt32s, width * sizeof(uint32_t)); |
|
436 |
// |
|
437 |
#endif // NO_QUARTZ |
|
438 |
||
439 |
%}. |
|
440 |
width isNil ifTrue:[ |
|
441 |
^ self primitiveFailed |
|
442 |
]. |
|
443 |
Transcript printf:'w:%d h:%d bpp:%d\n' withAll:{ width . height . bytesPerPixel }. |
|
444 |
||
445 |
depth := bytesPerPixel * 8. |
|
446 |
||
447 |
Transcript printf:'d:%d\n' withAll:{ depth }. |
|
448 |
||
449 |
"/ MUST swap r and b channels - sigh |
|
450 |
"/ pixels swapBGRtoRGB |
|
451 |
||
452 |
img := Image extent:(width @ height) depth:depth bits:pixels. |
|
453 |
depth >= 24 ifFalse:[ |
|
454 |
"/ check what we get here... |
|
455 |
^ self primitiveFailed:'unsupported depth' |
|
456 |
]. |
|
457 |
||
458 |
img bitsPerSample:#[8 8 8]. |
|
459 |
img samplesPerPixel:3. |
|
460 |
img photometric:#rgb. |
|
461 |
^ img |
|
462 |
! ! |
|
463 |
||
14819 | 464 |
!OSXOperatingSystem class methodsFor:'documentation'! |
465 |
||
466 |
version |
|
19817 | 467 |
^ '$Header$' |
14819 | 468 |
! |
469 |
||
470 |
version_CVS |
|
19817 | 471 |
^ '$Header$' |
14819 | 472 |
! ! |