git.fiddlerwoaroof.com
Browse code

(init)

Ed L authored on 04/01/2018 19:59:46
Showing 4 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,101 @@
1
+(defpackage :demo-app
2
+  (:use :cl :objc-runtime)
3
+  (:export ))
4
+(in-package :demo-app)
5
+(named-readtables:in-readtable :objc-readtable)
6
+
7
+(cffi:defcallback exception-handler :void ((exception :pointer))
8
+  (with-selectors (reason)
9
+    (format t "~&Exxception: ~a~%" [exception reason])
10
+    (values)))
11
+
12
+
13
+#+null
14
+(cffi:defcfun (set-uncaught-exception-handler "set_uncaught_exception_handler"
15
+                                              :library objc-runtime::expose-stuff)
16
+    :void
17
+  (cb :pointer))
18
+
19
+(defun call-with-rect (x y w h cb)
20
+  (check-type x real)
21
+  (check-type y real)
22
+  (check-type w real)
23
+  (check-type h real)
24
+  (cffi:with-foreign-object (rect '(:struct ns-rect))
25
+    (cffi:with-foreign-slots (((:pointer ns-rect-origin) (:pointer ns-rect-size))
26
+                              rect (:struct ns-rect))
27
+      (cffi:with-foreign-slots ((ns-point-x ns-point-y) ns-rect-origin (:struct ns-point))
28
+        (setf ns-point-x (coerce x 'double-float)
29
+              ns-point-y (coerce y 'double-float)))
30
+      (cffi:with-foreign-slots ((ns-size-width ns-size-height)
31
+                                ns-rect-size (:struct ns-size))
32
+        (setf ns-size-width (coerce w 'double-float)
33
+              ns-size-height (coerce h 'double-float))))
34
+    (funcall cb rect)))
35
+
36
+(defun call-with-point (x y cb)
37
+  (check-type x real)
38
+  (check-type y real)
39
+  (cffi:with-foreign-object (point '(:struct ns-point))
40
+    (cffi:with-foreign-slots ((ns-point-x ns-point-y) point (:struct ns-point))
41
+      (setf ns-point-x (coerce x 'double-float)
42
+            ns-point-y (coerce y 'double-float)))
43
+    (funcall cb point)))
44
+
45
+(defmacro with-rect ((rect (x y) (w h)) &body body)
46
+  `(call-with-rect ,x ,y ,w ,h
47
+                   (lambda (,rect)
48
+                     ,@body)))
49
+
50
+(defmacro with-point ((point (x y)) &body body)
51
+  `(call-with-point ,x ,y
52
+                   (lambda (,point)
53
+                     ,@body)))
54
+
55
+(defun make-rect (x y w h)
56
+  (check-type x real)
57
+  (check-type y real)
58
+  (check-type w real)
59
+  (check-type h real)
60
+  (cffi:convert-to-foreign `(ns-rect-origin
61
+                             (objc-runtime:ns-point-x
62
+                              ,(coerce x 'double-float)
63
+                              objc-runtime:ns-point-y
64
+                              ,(coerce y 'double-float))
65
+                             ns-rect-size
66
+                             (objc-runtime:ns-size-width
67
+                              ,(coerce w 'double-float)
68
+                              objc-runtime:ns-size-height
69
+                              ,(coerce h 'double-float)))
70
+                           '(:struct objc-runtime:ns-rect)))
71
+
72
+(defun main ()
73
+  (with-selectors ((shared-application "sharedApplication")
74
+                   (process-info "processInfo")
75
+                   (process-name "processName")
76
+                   (set-activation-policy "setActivationPolicy:")
77
+                   (init-with-content-rect "initWithContentRect:styleMask:backing:defer:")
78
+                   (set-title "setTitle:")
79
+                   (run "run")
80
+                   (activate-ignoring-other-apps "activateIgnoringOtherApps:")
81
+                   alloc
82
+                   (make-key-and-order-front "makeKeyAndOrderFront:")
83
+                   (cascade-top-left-from-point "cascadeTopLeftFromPoint:")
84
+                   ;; (application-should-terminate "applicationShouldTerminate:")
85
+                   ;; (set-delegate "setDelegate:")
86
+                   ;; (finish-launching "finishLaunching")
87
+                   )
88
+    [#@NSApplication shared-application]
89
+    [objc-runtime::ns-app set-activation-policy :int 0]
90
+
91
+    (break)
92
+    (let* ((application-name [[#@NSProcessInfo process-info] process-name]))
93
+      (with-point (p (20 20))
94
+        (let* ((the-window [#@NSWindow alloc]))
95
+          [the-window init-with-content-rect :pointer (make-rect 10 10 120 120)
96
+                                             :char 1 :char 2 :boolean nil]
97
+          [the-window cascade-top-left-from-point :pointer p]
98
+          [the-window set-title :pointer application-name]
99
+          [the-window make-key-and-order-front :pointer (cffi:null-pointer)]
100
+          [ objc-runtime::ns-app activate-ignoring-other-apps :boolean t]
101
+          [ objc-runtime::ns-app run])))))
0 102
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+(in-package :objc-runtime)
2
+
3
+(include "Foundation/NSGeometry.h")
4
+(include "AppKit/NSWindow.h")
5
+(include "AppKit/NSGraphics.h")
6
+
7
+(cc-flags "-x objective-c -framework Foundation -framework AppKit -ObjC")
8
+
9
+(cstruct ns-point "NSPoint"
10
+         (ns-point-x "x" :type :double)
11
+         (ns-point-y "y" :type :double))
12
+
13
+(cstruct ns-size "NSSize"
14
+         (ns-size-width "width" :type :double)
15
+         (ns-size-height "height" :type :double))
16
+
17
+(cstruct ns-rect "NSRect"
18
+         (ns-rect-origin "origin" :type (:struct ns-point))
19
+         (ns-rect-size "size" :type (:struct ns-size)))
20
+
21
+(cenum (ns-window-style-mask)
22
+       ((:ns-window-style-mask-borderless "NSWindowStyleMaskBorderless"))
23
+       ((:ns-window-style-mask-titled "NSWindowStyleMaskTitled"))
24
+       ((:ns-window-style-mask-closable "NSWindowStyleMaskClosable"))
25
+       ((:ns-window-style-mask-miniaturizable "NSWindowStyleMaskMiniaturizable"))
26
+       ((:ns-window-style-mask-resizable "NSWindowStyleMaskResizable")))
27
+
28
+(cenum (ns-backing-store-type)
29
+       ((:ns-backing-store-retained "NSBackingStoreRetained"))
30
+       ((:ns-backing-store-Nonretained "NSBackingStoreNonretained"))
31
+       ((:ns-backing-store-buffered "NSBackingStoreBuffered")))
0 32
new file mode 100644
... ...
@@ -0,0 +1,184 @@
1
+(in-package :objc-runtime)
2
+
3
+(serapeum:eval-always
4
+  (cffi:define-foreign-library cocoa
5
+    (:darwin (:framework "Cocoa")))
6
+  (define-foreign-library foundation
7
+    (:darwin (:framework "Foundation")))
8
+  (define-foreign-library appkit
9
+    (:darwin (:framework "AppKit")))
10
+  (define-foreign-library expose-stuff
11
+    (:darwin #p"./libnsrect-expose.dylib")))
12
+
13
+
14
+(use-foreign-library foundation)
15
+(use-foreign-library cocoa)
16
+(use-foreign-library appkit)
17
+(use-foreign-library expose-stuff)
18
+
19
+(defctype o-class :pointer)
20
+(defctype o-selector :pointer)
21
+
22
+(defcfun (objc-look-up-class "objc_lookUpClass" :library foundation)
23
+    o-class
24
+  (name :string))
25
+
26
+(defcfun (objc-allocate-class-pair "objc_allocateClassPair" :library foundation)
27
+    :pointer
28
+  (superclass :pointer)
29
+  (name :string)
30
+  (extra-bytes :int))
31
+
32
+(defcfun (objc-get-protocol "objc_getProtocol" :library foundation)
33
+    :pointer
34
+  (name :string))
35
+
36
+(defcfun (class-add-protocol "class_addProtocol" :library foundation)
37
+    :boolean
38
+  (class :pointer)
39
+  (protocol :pointer))
40
+
41
+(defcfun (class-add-method "class_addMethod" :library foundation)
42
+    :boolean
43
+  (class :pointer)
44
+  (selector :pointer)
45
+  (cb :pointer)
46
+  (type :string))
47
+
48
+(defcfun (objc-class-get-name "class_getName" :library foundation)
49
+    :string
50
+  (cls o-class))
51
+
52
+(defcfun (objc-class-get-superclass "class_getSuperclass" :library foundation)
53
+    :pointer
54
+  (cls o-class))
55
+
56
+(defcfun (objc-get-class-list "objc_getClassList" :library foundation)
57
+    :int
58
+  (cls-buffer o-class)
59
+  (buffer-count :int))
60
+
61
+(defcfun (sel-register-name "sel_registerName" :library foundation)
62
+    o-selector
63
+  (name :string))
64
+
65
+(defcfun (objc-msg-send "objc_msgSend")
66
+    :pointer
67
+  (cls o-class)
68
+  (sel o-selector)
69
+  &rest)
70
+
71
+(defcfun (class-copy-method-list "class_copyMethodList" :library foundation)
72
+    :pointer
73
+  (cls o-class)
74
+  (numMethods (:pointer :int)))
75
+
76
+(defcfun (method-get-name "method_getName")
77
+    :pointer
78
+  (method :pointer))
79
+
80
+(defcfun (sel-get-name "sel_getName")
81
+    :string
82
+  (sel o-selector))
83
+
84
+(defgeneric get-methods (class)
85
+  (:method ((class string))
86
+    (get-methods (objc-look-up-class class)))
87
+  #+sbcl
88
+  (:method ((class sb-sys:system-area-pointer))
89
+    (with-foreign-object (num-methods :int)
90
+      (let ((methods (class-copy-method-list class num-methods)))
91
+        (let ((result (list)))
92
+          (dotimes (n (mem-aref num-methods :int) (nreverse result))
93
+            (push (mem-aref methods :pointer n)
94
+                  result)))))))
95
+
96
+(defun get-method-names (thing)
97
+  (mapcar (alexandria:compose #'sel-get-name
98
+                              #'method-get-name)
99
+          (get-methods thing)))
100
+
101
+(defgeneric graph->dot (graph stream)
102
+  (:method :around (graph stream)
103
+	   (format stream "~&digraph {~%~4trankdir=LR;~%")
104
+	   (call-next-method)
105
+	   (format stream "~&}"))
106
+  (:method ((graph hash-table) stream)
107
+    (loop for class being the hash-keys of graph using (hash-value superclass)
108
+       do (format stream "~&~4t\"~a\" -> \"~a\"~%" class superclass))))
109
+
110
+(defparameter *selector-cache* (make-hash-table :test 'equal))
111
+
112
+(defun ensure-selector (name)
113
+  (alexandria:ensure-gethash name *selector-cache*
114
+                             (sel-register-name name)))
115
+
116
+(defmacro with-selectors ((&rest selector-specs) &body body)
117
+  `(let (,@(mapcar (fw.lu:destructuring-lambda ((sym foreign-selector))
118
+                     `(,sym (ensure-selector ,foreign-selector)))
119
+                   (mapcar (fw.lu:glambda (spec)
120
+                             (:method ((spec symbol))
121
+                               (list spec (string-downcase spec)))
122
+                             (:method ((spec cons))
123
+                               (list (car spec) (cadr spec))))
124
+                           selector-specs)))
125
+     ,@body))
126
+
127
+(defmacro with-objc-classes ((&rest class-defs) &body body)
128
+  `(let (,@(mapcar (fw.lu:destructuring-lambda ((lisp-name foreign-name))
129
+                     `(,lisp-name (objc-look-up-class ,foreign-name)))
130
+                   class-defs))
131
+     ,@body))
132
+
133
+
134
+(eval-when (:compile-toplevel :load-toplevel :execute)
135
+  (named-readtables:defreadtable :objc-readtable
136
+    (:merge :standard)
137
+    (:syntax-from :standard #\) #\])
138
+    (:macro-char #\[ (lambda (s char)
139
+                       char
140
+                       (destructuring-bind (obj message . args)
141
+                           (read-delimited-list #\] s t)
142
+                         `(objc-msg-send ,obj ,message ,@args)))
143
+                 nil)
144
+    (:dispatch-macro-char #\# #\@
145
+                          (lambda (s c b)
146
+                            c b
147
+                            (let ((class-name (coerce (loop for c = (read-char s nil nil t)
148
+                                                         until (or (null c)
149
+                                                                   (serapeum:whitespacep c))
150
+                                                         collect c)
151
+                                                      'string)))
152
+                              `(objc-look-up-class ,class-name))))))
153
+
154
+(named-readtables:in-readtable :objc-readtable)
155
+
156
+(defgeneric make-objc-instance (class &rest args)
157
+  (:method ((class string) &rest args)
158
+    (apply #'make-objc-instance (objc-look-up-class class) args))
159
+  #+ccl
160
+  (:method ((class ccl:macptr) &rest args)
161
+    (declare (ignore args))
162
+    (with-selectors (alloc init)
163
+      [[class alloc] init]))
164
+  #+sbcl
165
+  (:method ((class sb-sys:system-area-pointer) &rest args)
166
+    (declare (ignore args))
167
+    (with-selectors (alloc init)
168
+      [[class alloc] init])))
169
+
170
+
171
+(cffi:defcvar (ns-app "NSApp" :library appkit) :pointer)
172
+
173
+#|
174
+(uiop:nest (with-selectors (alloc init drain))
175
+           (with-objc-classes ((nsobject "NSAutoreleasepool")))
176
+           (eval-objc (objc-msg-send
177
+                       (objc-msg-send
178
+                        (objc-msg-send nsobject alloc)
179
+                        init)
180
+                       drain)))
181
+(with-selectors (alloc init))
182
+
183
+|#
184
+
0 185
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+(defpackage :objc-runtime/package
2
+  (:use :cl )
3
+  (:export ))
4
+(in-package :objc-runtime/package)
5
+
6
+(defpackage :objc-runtime
7
+  (:use :cl :cffi)
8
+  (:export
9
+   #:defmacro
10
+   #:*objc-readtable*
11
+   #:with-selectors
12
+   #:objc-msg-send
13
+   #:with-objc-classes
14
+   #:make-objc-instance
15
+   #:objc-readtable
16
+   #:ns-size-width
17
+   #:ns-size-height
18
+   #:ns-rect-origin
19
+   #:ns-rect-size
20
+   #:ns-point-x
21
+   #:ns-point-y
22
+   #:ns-point
23
+   #:ns-size
24
+   #:ns-rect))