-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.pb
549 lines (460 loc) · 18.1 KB
/
main.pb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
EnableExplicit
#MAINWIN = 1
#MAINTIMER = 2
#MAXWINDOWS = 100
;AXUIELEMENT: https://developer.apple.com/reference/applicationservices/axuielement.h?language=objc
;Getting unique windows: http://stackoverflow.com/questions/311956/getting-a-unique-id-for-a-window-of-another-application
;---------------------EXTERNAL------------------------
ImportC "-framework ApplicationServices"
AXUIElementCreateApplication(pid.i)
AXUIElementCopyAttributeValues(element, attribute, index, maxValues, *value)
AXUIElementCopyAttributeValue(element, attribute, *value)
AXIsProcessTrustedWithOptions(options)
AXValueCreate(theType, *valuePtr)
AXUIElementSetAttributeValue(element, attribute, value)
AXUIElementPerformAction(element, action)
AXValueGetValue(value, theType, *valuePtr)
CFDictionaryGetValue(_1,_2)
CFStringCreateWithCharacters.i (*alloc, *bytes, numChars.i)
CFStringCompare(theString1, theString2, compareOptions);
CFArrayCreate(allocator, *values, numValues, *callBacks)
CFArrayGetCount(theArray)
CFArrayGetValueAtIndex(theArray, idx)
CFStringGetSystemEncoding()
CFUserNotificationDisplayNotice(Timeout.d, AlertLevel.i, IconUrl.l, SoundUrl.l, LocalizationUrl.l, Title.l, Message.l, DefBtnTitle.l)
CFStringGetCStringPtr(l1,l2)
CFStringGetCString(CFStringRef, *StringBuffer, BufferSize.i, CFStringEncoding.i)
CFBooleanGetValue(boolean)
CFRelease(cf)
CGWindowListCopyWindowInfo(option, relativeToWindow = 0)
AXObserverCreate(apppid, callback, *outObserver);
AXObserverAddNotification(observer, element, notification, *refcon)
AXObserverRemoveNotification(observer, element, notification)
CFRunLoopAddSource(rl, source, mode);
CFRunLoopRun()
CFRunLoopStop(rl)
AXObserverGetRunLoopSource(observer);
EndImport
Global.i kCFBooleanTrue
Global.i kCFBooleanFalse
!mov rax, qword [kCFBooleanTruePtr]
!mov rdx, qword [kCFBooleanFalsePtr]
!mov rax, [rax]
!mov rdx, [rdx]
!mov [v_kCFBooleanTrue], rax
!mov [v_kCFBooleanFalse], rdx
DataSection
!extern _kCFBooleanTrue
!extern _kCFBooleanFalse
!kCFBooleanTruePtr: dq _kCFBooleanTrue
!kCFBooleanFalsePtr: dq _kCFBooleanFalse
EndDataSection
#NSImageLeft = 2
#NSApplicationActivationPolicyRegular = 0
#NSApplicationActivationPolicyAccessory = 1
#NSApplicationActivationPolicyProhibited = 2
#kAXValueCGPointType = 1
#kAXValueCGSizeType = 2
#kSetFrontProcessFrontWindowOnly = 1
#NSApplicationActivateAllWindows = 1 << 0
#NSApplicationActivateIgnoringOtherApps = 1 << 1
;Window List Option Constants
#kCGWindowListOptionAll = 0
#kCGWindowListOptionOnScreenOnly = (1 << 0)
#kCGWindowListOptionOnScreenAboveWindow = (1 << 1)
#kCGWindowListOptionOnScreenBelowWindow = (1 << 2)
#kCGWindowListOptionIncludingWindow = (1 << 3)
#kCGWindowListExcludeDesktopElements = (1 << 4)
;-------------------------------------------------------
;-----------------------MACROS---------------------------
Macro DoubleQuote
"
EndMacro
Macro defKValue(name)
Global name#_STR.s = DoubleQuote#name#DoubleQuote
Global name = CFStringCreateWithCharacters(#Null, @name#_STR, Len(name#_STR))
EndMacro
;---------------------------------------------------------
;----------------------GLOBAL/STRUCT----------------------
Structure Window
index.i
localindex.i
pid.i
app_title.s
win_title.s
icon.i
x.i
y.i
w.i
h.i
observerRef.i
observerRef2.i
appref.i
nowin.b
timecreated.i
EndStructure
Global G_EntryHeight.i = 32
Global G_EntryWidth.i = 128
Global G_sharedapp.i = CocoaMessage(0,0,"NSApplication sharedApplication")
Global G_workspace.i = CocoaMessage(0,0, "NSWorkspace sharedWorkspace")
Global G_thispid.i = 0
Global G_LastWinCount = 0
;for app notify
Global G_dncenter = CocoaMessage(0, 0, "NSDistributedNotificationCenter defaultCenter")
Global G_ncenter = CocoaMessage(0, G_workspace, "notificationCenter")
Global G_appdelegate = CocoaMessage(0, G_sharedapp, "delegate")
Global G_delegateclass = CocoaMessage(0, G_appdelegate, "class")
;Global G_dncenter = CocoaMessage(0, 0, "NSDistributedNotificationCenter defaultCenter")
Global G_observerRef
Global G_currentRunloop
Global NewList G_taskbar_items.window()
;Global NewList G_taskbar_currentpids.i()
Declare AddObserver(pid, element, notificationtype)
Declare RemoveObserver(observerRef, element, notificationtype)
defKValue(AXMain)
defKValue(AXWindows)
defKValue(AXFocused)
defKValue(AXFocusedWindow)
defKValue(AXHidden)
defKValue(AXFrontmost)
defKValue(AXRaise)
defKValue(AXMinimized)
defKValue(AXTitle)
defKValue(AXPosition)
defKValue(AXCloseButton)
defKValue(AXPress)
defKValue(AXSize)
defKValue(AXWindowCreated)
defKValue(AXMainWindowChanged)
defKValue(AXUIElementDestroyed)
defKValue(AXResized)
defKValue(kCFRunLoopDefaultMode)
;--------------------------------------------------------
;----------------------PROCEDURES------------------------
Procedure GetCurrentDesktopWidth()
ExamineDesktops()
ProcedureReturn DesktopWidth(0)
EndProcedure
Procedure GetCurrentDesktopHeight()
ExamineDesktops()
ProcedureReturn DesktopHeight(0)
EndProcedure
Procedure GetDesktopLowerYPosition(yoffset)
ProcedureReturn GetCurrentDesktopHeight() - yoffset
EndProcedure
Procedure.s GetNSRunningAppName(appobj)
Define lname = CocoaMessage(0,appobj,"localizedName")
If lname
Define lname_str.s = PeekS(CocoaMessage(0, lname, "UTF8String"), -1, #PB_UTF8)
ProcedureReturn lname_str
Else
ProcedureReturn ""
EndIf
EndProcedure
Procedure.s CFStringToStr(cfstringref.i)
If cfstringref = 0 : ProcedureReturn "" : EndIf
;CFUserNotificationDisplayNotice(0,1, #Null,#Null, #Null, cfstringref, cfstringref, #Null)
;Define String.s = Space(256)
ProcedureReturn PeekS(CocoaMessage(0, cfstringref, "UTF8String"), -1, #PB_UTF8)
;CFStringGetCString(cfstringref, @String, Len(String), 0)
;Define tmp.s = Trim(PeekS(@String, -1, #PB_UTF8))
;MessageRequester(tmp, tmp)
;ProcedureReturn tmp
EndProcedure
Procedure GetCurrentWinCount()
Define w = CGWindowListCopyWindowInfo(#kCGWindowListOptionAll)
Define wincount = CFArrayGetCount(w)
CFRelease(w)
ProcedureReturn wincount
EndProcedure
Procedure RefreshTaskbar()
ResizeWindow(#MAINWIN, 0,GetDesktopLowerYPosition(G_EntryHeight), GetCurrentDesktopWidth(), G_EntryHeight)
;clear gadgets
ForEach G_taskbar_items()
If G_taskbar_items()\observerRef <> 0
RemoveObserver(G_taskbar_items()\observerRef, G_taskbar_items()\appref, AXWindowCreated)
CFRelease(G_taskbar_items()\observerRef)
EndIf
If G_taskbar_items()\observerRef2 <> 0
RemoveObserver(G_taskbar_items()\observerRef2, G_taskbar_items()\appref, AXUIElementDestroyed)
CFRelease(G_taskbar_items()\observerRef2)
EndIf
If G_taskbar_items()\appref <> 0
CFRelease(G_taskbar_items()\appref)
EndIf
If G_taskbar_items()\index <> -1
FreeGadget(G_taskbar_items()\index)
EndIf
Next
;Debug "REFRESH"
ClearList(G_taskbar_items())
;ClearList(G_taskbar_currentpids())
;GET CURRENT WINDOWS AND PUT IN LIST
Define runningapps = CocoaMessage(0,G_workspace,"runningApplications")
Define count = CocoaMessage(0,runningapps,"count")
Define i = 0
For i = 0 To count - 1
Define current_app = CocoaMessage(0,runningapps,"objectAtIndex:",i)
If current_app
If CocoaMessage(0,current_app,"activationPolicy") = #NSApplicationActivationPolicyRegular
Define appname.s = GetNSRunningAppName(current_app)
;get windows object for current app
Define pid = CocoaMessage(0, current_app, "processIdentifier")
If G_thispid = pid
Continue
EndIf
;AddElement(G_taskbar_currentpids())
;G_taskbar_currentpids() = pid
Define appref = AXUIElementCreateApplication(pid)
Define appwindows
AXUIElementCopyAttributeValues(appref, AXWindows, 0, #MAXWINDOWS, @appwindows);
If appwindows = 0: CFRelease(appref) : Continue : EndIf
;get icon and resize
Define icon = CocoaMessage(0, current_app, "icon")
Define icon_size.NSSize
icon_size\height = G_EntryHeight * 0.8
icon_size\width = G_EntryHeight * 0.8
CocoaMessage(0, icon, "setSize:@", @icon_size)
;iterate through windows
Define j = 0
Define win = 0
Define cli = -1
Define wincount = 0
For j = 0 To CFArrayGetCount(appwindows) -1
Define title
win = CFArrayGetValueAtIndex(appwindows, j)
AXUIElementCopyAttributeValue(win, AXTitle, @title)
If CFStringToStr(title) = "" And appname = "Finder"
Continue
EndIf
;get window position
Define posref = 0
Define pos_val.CGPoint
AXUIElementCopyAttributeValue(win, AXPosition, @posref)
If posref
AXValueGetValue(posref, #kAXValueCGPointType,@pos_val)
EndIf
;get window width height
Define sizeref = 0
Define size_val.CGSize
AXUIElementCopyAttributeValue(win, AXSize, @sizeref)
If sizeref
AXValueGetValue(sizeref, #kAXValueCGSizeType, @size_val)
EndIf
;adjust window when required
Define lowerypos = GetDesktopLowerYPosition(G_EntryHeight)
If pos_val\y + size_val\height > lowerypos
Define newsize.CGSize
newsize\width = size_val\width
newsize\height = size_val\height - (pos_val\y + size_val\height - lowerypos)
Define newsizeaxval = AXValueCreate(#kAXValueCGSizeType, newsize)
AXUIElementSetAttributeValue(win, AXSize, newsizeaxval)
size_val\height = newsize\height
EndIf
;add notify
;Define observerref = AddObserver(pid, win, AXResized)
AddElement(G_taskbar_items())
G_taskbar_items()\app_title = appname
G_taskbar_items()\win_title = CFStringToStr(title)
G_taskbar_items()\pid = pid
G_taskbar_items()\localindex = j
G_taskbar_items()\icon = CocoaMessage(0, current_app, "icon")
G_taskbar_items()\x = pos_val\x
G_taskbar_items()\y = pos_val\y
G_taskbar_items()\w = size_val\width
G_taskbar_items()\h = size_val\height
G_taskbar_items()\icon = icon
G_taskbar_items()\timecreated = ElapsedMilliseconds()
If j = 0
G_taskbar_items()\observerRef = AddObserver(pid,appref, AXWindowCreated)
G_taskbar_items()\observerRef2 = AddObserver(pid, appref, AXUIElementDestroyed)
G_taskbar_items()\appref = appref
EndIf
If cli = -1
cli = ListIndex(G_taskbar_items())
EndIf
wincount + 1
Next
;sort windows for app so they stay in place
If wincount <> 1 And cli >= 0
SortStructuredList(G_taskbar_items(),#PB_Sort_Ascending, OffsetOf(Window\win_title), TypeOf(Window\win_title), cli,cli + wincount - 1)
EndIf
If ListSize(G_taskbar_items()) = 0
AddElement(G_taskbar_items())
G_taskbar_items()\observerRef = AddObserver(pid,appref, AXWindowCreated)
G_taskbar_items()\observerRef2 = AddObserver(pid, appref, AXUIElementDestroyed)
G_taskbar_items()\appref = appref
G_taskbar_items()\nowin = #True
G_taskbar_items()\index = -1
EndIf
CFRelease(win)
EndIf
EndIf
;FILL THE TASKBAR
Define taskentry_h = G_EntryHeight
Define taskentry_w = G_EntryWidth
Define nowx = 0
Define nowy = 0
Define gadgetnow = 0
;START BUTTON
gadgetnow + 1
ButtonGadget(gadgetnow, 0, 0, taskentry_h, taskentry_h, "S")
CocoaMessage(0, GadgetID(gadgetnow), "setBezelStyle:", @"NSShadowlessSquareBezelStyle")
nowx = nowx + taskentry_h
ForEach G_taskbar_items()
If G_taskbar_items()\nowin = #True : Continue : EndIf
gadgetnow+1
; ButtonImageGadget(gadgetnow, nowx, 0, taskentry_w, taskentry_h, G_taskbar_items()\icon, G_taskbar_items()\win_title,#PB_Button_Default|#PB_Button_Toggle)
; CocoaMessage(0, GadgetID(cmd_1), "setBezelStyle:", GetGadgetState(spn_1))
ButtonGadget(gadgetnow, nowx, 0, taskentry_w, taskentry_h, G_taskbar_items()\win_title,#PB_Button_Default)
CocoaMessage(0, GadgetID(gadgetnow), "setBezelStyle:", @"NSShadowlessSquareBezelStyle")
;CocoaMessage(0, GadgetID(gadgetnow), "setTitle:$", @"TEST")
CocoaMessage(0, GadgetID(gadgetnow), "setImage:", G_taskbar_items()\icon)
CocoaMessage(0, GadgetID(gadgetnow), "setImagePosition:", #NSImageLeft)
;CocoaMessage(0, GadgetID(gadgetnow), "highlight:", #YES)
nowx+taskentry_w
G_taskbar_items()\index = gadgetnow
Next
Next
G_LastWinCount = GetCurrentWinCount()
EndProcedure
Procedure WindowToFront(pid .i, localindex.i, act_deact.b = #True)
Define appref = AXUIElementCreateApplication(pid)
Define appwindows
AXUIElementCopyAttributeValues(appref, AXWindows, 0, 100, @appwindows);
If appwindows = 0: ProcedureReturn #False : EndIf
Define runapp = CocoaMessage(0, 0, "NSRunningApplication runningApplicationWithProcessIdentifier:", pid)
;AXUIElementSetAttributeValue(appref, AXHidden, kCFBooleanTrue)
;iterate through windows
Define j = 0
Define win = 0
For j = 0 To CFArrayGetCount(appwindows) -1
If localindex = j
win = CFArrayGetValueAtIndex(appwindows, j)
AXUIElementSetAttributeValue(win, AXMain, kCFBooleanTrue)
AXUIElementPerformAction(win, AXRaise)
CocoaMessage(0,runapp, "activateWithOptions:", #NSApplicationActivateIgnoringOtherApps )
EndIf
Next
CFRelease(appref)
;CocoaMessage(0, runapp, "release")
RefreshTaskbar()
EndProcedure
Procedure ActivateTaskbarItem(eventnum)
;toggle button
Define state = GetGadgetData(eventnum)
If state = #True
SetGadgetData(eventnum, #False)
Else
SetGadgetData(eventnum, #True)
EndIf
ForEach G_taskbar_items()
If G_taskbar_items()\index = eventnum
WindowToFront(G_taskbar_items()\pid, G_taskbar_items()\localindex, GetGadgetData(eventnum))
EndIf
Next
EndProcedure
Procedure CheckWindowCount()
Define wincount = GetCurrentWinCount()
If G_LastWinCount <> wincount
RefreshTaskbar()
EndIf
EndProcedure
ProcedureC ObserverCallback()
RefreshTaskbar()
EndProcedure
Procedure AddObserver(pid, element, notificationtype)
;http://stackoverflow.com/questions/853833/how-can-my-app-detect-a-change-To-another-apps-window
Define observerRef = 0
AXObserverCreate( pid, @ObserverCallback(), @observerRef )
If observerRef
Define currentloop = CocoaMessage(0, 0,"NSRunLoop currentRunLoop")
Define rl= CocoaMessage(0, currentloop, "getCFRunLoop")
Define source=AXObserverGetRunLoopSource(observerRef)
CFRunLoopAddSource(rl,source,kCFRunLoopDefaultMode)
AXObserverAddNotification( observerRef, element, notificationtype, #nil );
EndIf
ProcedureReturn observerRef
EndProcedure
Procedure RemoveObserver(observerRef, element, notificationtype)
AXObserverRemoveNotification(observerRef, element,notificationtype)
EndProcedure
; Procedure CheckWindowCountOld(obj,sel,notification)
; Define nameobj.i= CocoaMessage(0,notification, "name")
; Debug 1
; If CFStringToStr(nameobj) = "com.apple.Carbon.TISNotifySelectedKeyboardInputSourceChanged"
; Define newtotal
; Define wintotal = ListSize(G_taskbar_items()) + 1
; ForEach G_taskbar_currentpids()
; If G_taskbar_currentpids() = 0 : Continue : EndIf
; Define appref = AXUIElementCreateApplication(G_taskbar_currentpids())
; Define appwindows
; AXUIElementCopyAttributeValues(appref, AXWindows, 0, #MAXWINDOWS, @appwindows);
; If appwindows = 0: CFRelease(appref) : Continue : EndIf
; newtotal + (CFArrayGetCount(appwindows))
; CFRelease(appref)
; Next
; Debug wintotal
; Debug newtotal
; Debug "--------"
; If wintotal <> newtotal
; RefreshTaskbar()
; EndIf
; EndIf
; EndProcedure
;Procedure Notify(obj,sel,notification)
;Debug "-------------------"
; Define nameobj.i= CocoaMessage(0,notification, "name")
; Define desc = CocoaMessage(0, notification, "object")
; Debug desc
; Debug CFStringToStr(desc)
;Debug CFStringToStr(desc)
;Define userNotification.i = CocoaMessage(0, userInfo, "objectForKey:$", @"NSApplicationLaunchUserNotificationKey")
; If CFStringToStr(nameobj) = "AppleSelectedInputSourcesChangedNotification"
; ;RefreshTaskbar()
; EndIf
;EndProcedure
;----------------------------------------------------------
;-----------------------MAINPROGRAM------------------------
;get pid of this app
Define tmpapp = CocoaMessage(0, 0, "NSRunningApplication currentApplication")
G_thispid = CocoaMessage(0, tmpapp, "processIdentifier")
OpenWindow(#MAINWIN, 0,GetDesktopLowerYPosition(G_EntryHeight), GetCurrentDesktopWidth(), G_EntryHeight, "TaskBar", #PB_Window_Tool| #PB_Window_BorderLess)
StickyWindow(#MAINWIN, #True)
RefreshTaskbar()
;code for when new app is launched or closed
Define selector = sel_registerName_("RefreshTaskbar")
class_addMethod_(G_delegateclass, selector, @RefreshTaskbar(), "v@:@")
CocoaMessage(0, G_ncenter, "addObserver:", G_appdelegate, "selector:", selector, "name:$", @"NSWorkspaceDidTerminateApplicationNotification", "object:", #nil)
CocoaMessage(0, G_ncenter, "addObserver:", G_appdelegate, "selector:", selector, "name:$", @"NSWorkspaceDidLaunchApplicationNotification", "object:", #nil)
CocoaMessage(0, G_ncenter, "addObserver:", G_appdelegate, "selector:", selector, "name:$", @"NSWorkspaceDidHideApplicationNotification", "object:", #nil) ;NSWorkspaceDidHideApplication
CocoaMessage(0, G_ncenter, "addObserver:", G_appdelegate, "selector:", selector, "name:$", @"NSWorkspaceDidUnhideApplicationNotification", "object:", #nil)
;Define selector_chkwinc = sel_registerName_("CheckWindowCount:")
;class_addMethod_(G_delegateclass, selector_chkwinc, @CheckWindowCount(), "v@:@")
;CocoaMessage(0, G_dncenter, "addObserver:", G_appdelegate, "selector:", selector_chkwinc, "name:", #nil, "object:", #nil)
;CocoaMessage(0, G_sharedapp, "setActivationPolicy:", #NSApplicationActivationPolicyAccessory)
Define eventnum = 0
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
eventnum = EventGadget()
Select eventnum
Case 1
Break
Default
ActivateTaskbarItem(eventnum)
EndSelect
Case #PB_Event_Menu
eventnum = EventMenu()
Select eventnum
Case 1
Default
EndSelect
Case #PB_Event_CloseWindow : Break
EndSelect
ForEver
CocoaMessage(0, G_ncenter, "removeObserver:", G_appdelegate, "name:$", @"NSWorkspaceDidTerminateApplicationNotification", "object:", #nil)
CocoaMessage(0, G_ncenter, "removeObserver:", G_appdelegate, "name:$", @"NSWorkspaceDidLaunchApplicationNotification", "object:", #nil)
CocoaMessage(0, G_ncenter, "removeObserver:", G_appdelegate, "name:$", @"NSWorkspaceDidHideApplicationNotification", "object:", #nil)
CocoaMessage(0, G_ncenter, "removeObserver:", G_appdelegate, "name:$", @"NSWorkspaceDidUnhideApplicationNotification", "object:", #nil)
;-----------------------------------------------------------