Carbon API list for Mac

Mac OSX specific forum
User avatar
Shardik
Addict
Addict
Posts: 1988
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Cross-platform examples with API functions extending PureBasic

Post by Shardik »

DoubleDutch wrote:It would be good if some of the examples where all three platforms had their own code would be added.
Cross-platform examples with API functions for all 3 platforms (keep in mind that some examples on MacOS are still only working for Carbon and don't work with Cocoa):
- Check if Gadget is disabled
- Check if Gadget is visable
- Display website in default browser
- Drag image from WebGadget onto ImageGadget and display image path
- Get double click time
- Get IP addresses from host name
- Get MAC address from remote computer
- Get computer name
- Get user idle time
- Get UTC Time from different countries
- OpenGL Demo

ButtonGadget:
- Toggle text justification between center and left

Custom Gadgets:
- TimePicker using SpinButtons and TextGadget
- Windows-like TimePicker

ComboBoxGadget:
- Enable and disable ComboBox and keep background white

Cursor:
- Change cursor into PNG image
- Hide and show cursor

EditorGadget:
- Add line and keep it visible
- Center text
- Convert text containing tags to RTF (supporting bold, italic and underlined characters)
- Detect right click and display context menu
- Enable word wrap
- Get number of lines
- Get single text line from wrapped text block
- Select line after line and keep line visible
- Search in EditorGadget for text line double clicked in a ListIconGadget and select that line
- Select and deselect all the text
- Set cursor

ExplorerListGadget:
- Select a row
- Select and unselect a row (without API)

ExplorerTreeGadget:
- Similar look and behaviour in Linux and MacOS as in Windows

HyperLinkGadget:
- Detect right click and display popup menu

ListIconGadget:
- Count number of columns
- Detect left click on cell
- Detect left click on header cell
- Detect movement of mouse wheel
- Display double-clicked row at top of list
- Display selected row in center of Gadget
- Get all selected items
- Get and set row height
- Get currently visible top row
- GetGadgetItemImage()
- Hide title header
- Set column justification
- Toggle multi selection of items

ListViewGadget:
- Get selected rows without iterating over all rows
- Get row at top of list

PanelGadget:
- Get absolute position of gadget on panel

ScrollBarGadget:
- Live scrolling

StringGadget:
- Align text right
- Autoselect text on mouse over gadget
- Center text
- Detect read only mode
- Detect right click and suppress context menu
- Get and set cursor position
- Get and set placeholder text
- Get and set selected text
- Set cursor to end of text
- Toggle read only state
- Toggle vertical centering

TextGadget:
- Toggle vertical centering

ToolBar:
- Detect if toolbar button is enabled or disabled

TreeGadget:
- Get row height
- GetGadgetItemImage()

WebGadget:
- Drag image from WebGadget to ImageGadget and display image path

Window:
- Change transparency
- Detect end of resizing
- Get background color of window and set same background color in CanvasGadget
- Set background image

Some examples have already been implemented in PB like "Get double click time", "Enable word wrap" or "Get computer name"... 8)

DoubleDutch wrote:Maybe there should be a special bit of the forum where you can post API code that works on all three platforms that Fred & co can consider for inclusion in the main code core?

It would be nice to have a subforum for cross-platform API code... :P
Last edited by Shardik on Thu Feb 01, 2024 12:13 pm, edited 42 times in total.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Carbon API list for Mac

Post by Keya »

Shardik wrote:
DoubleDutch wrote:Maybe there should be a special bit of the forum where you can post API code that works on all three platforms that Fred & co can consider for inclusion in the main code core?
It would be nice to have a subforum for cross-platform API code... :P
^ This! (again! still! why not!?) :)

and thankyou Shardik, your Center Text demo works well :)

Shardik ps. in your demo if the OS is <= XP you "overwrite" the Gadget by recreating another one with the same ID (neat trick for re-styling! :)) ... so, the equivalent of
StringWindow(0, ...
StringWindow(0, ...

Im just wondering IS IT SAFE to use this overwrite trick that way, or should there be a FREEGADGET() call between those two?
It seems to work fine without FreeGadget but im wondering if its a resource leak, though when i checked in Windows Task Manager it showed the same number of Handles both with and without the FreeGadget call so perhaps internally FreeGadget is already being called, i dont know! but i dont know how to test for handle leak in linux or mac

For example...

Code: Select all

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  ImportC ""
    gtk_entry_set_alignment(Entry.I, XAlign.F)
  EndImport
CompilerEndIf

Procedure CenterEditGadgetText(GadgetConst)
CompilerSelect #PB_Compiler_OS               
  CompilerCase #PB_OS_Linux
    gtk_entry_set_alignment(GadgetID(GadgetConst), 0.5)
  CompilerCase #PB_OS_MacOS
    CocoaMessage(0, GadgetID(GadgetConst), "setAlignment:", 2)
  CompilerCase #PB_OS_Windows
    If OSVersion() > #PB_OS_Windows_XP
      SetWindowLongPtr_(GadgetID(GadgetConst), #GWL_STYLE, GetWindowLongPtr_(GadgetID(0), #GWL_STYLE) & $FFFFFFFC | #ES_CENTER)
    Else
      OldTxt.s = GetGadgetText(GadgetConst)
      OldX = GadgetX(GadgetConst): OldY = GadgetY(GadgetConst): OldW = GadgetWidth(GadgetConst): OldH = GadgetHeight(GadgetConst)
      FreeGadget(GadgetConst)
      StringGadget(GadgetConst, OldX, OldY, OldW, OldH, OldTxt, #ES_CENTER)
    EndIf
CompilerEndSelect
EndProcedure


#Edit1 = 1

OpenWindow(0, 100, 100, 280, 70, "StringGadget with centered text", #PB_Window_SystemMenu)

StringGadget(#Edit1, 20, 20, 240, 21, "Centered text")
CenterEditGadgetText(#Edit1)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Carbon API list for Mac

Post by Keya »

I try Shardik's excellent example for listing processes - http://www.purebasic.fr/english/viewtop ... 53#p375953
it gets the Process ID list fine (not anywhere near as many as 'ps -x' though?) but is crashing (PB v5.31-64/Mac 10.10-64) getting the process name with invalid memory access in this function:

Code: Select all

Procedure.S ConvertCFStringIntoString(CFStringRef.L)
  Protected Encoding.L
  Protected String.S = Space(256)
  If #PB_Compiler_Unicode
    Encoding = #kCFStringEncodingUnicode
  Else
    Encoding = #kCFStringEncodingMacRoman
  EndIf
  CFStringGetCString(CFStringRef, @String, Len(String), Encoding)      ;<-- Crash
  CFRelease(CFStringRef)
  ProcedureReturn Trim(String)
EndProcedure
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Carbon API list for Mac

Post by wilbert »

Keya wrote:I try Shardik's excellent example for listing processes - http://www.purebasic.fr/english/viewtop ... 53#p375953
it gets the Process ID list fine (not anywhere near as many as 'ps -x' though?) but is crashing (PB v5.31-64/Mac 10.10-64) getting the process name with invalid memory access in this function:
The code isn't ready for 64 bit. Also some things can be done easier now we got Cocoa support.
Here's some workarounds.

1. Code from Shardik adapted to support 64 bit and use Cocoa to retrieve the string

Code: Select all

EnableExplicit

#kNoProcess = 0

ImportC ""
  CopyProcessName(*ProcessSerialNumber, *Name)
  GetNextProcess(*ProcessSerialNumber)
  GetProcessPID(*ProcessSerialNumber, *PID)
EndImport

Structure ProcessSerialNumber
  HighLongOfPSN.l
  LowLongOfPSN.l
EndStructure

Define PID.i
Define ProcessNameRef.i
Define PSN.ProcessSerialNumber

PSN\HighLongOfPSN = 0
PSN\LowLongOfPSN = #kNoProcess

Repeat
  If GetNextProcess(@PSN.ProcessSerialNumber) = 0
    If PSN\LowLongOfPSN <> #kNoProcess
      If GetProcessPID(@PSN, @PID) = 0
        If CopyProcessName(@PSN, @ProcessNameRef) = 0
          Debug "PID = " + Str(PID) + ": " + PeekS(CocoaMessage(0, ProcessNameRef, "UTF8String"), -1, #PB_UTF8)
        EndIf
      EndIf
    EndIf
  EndIf
Until PSN\LowLongOfPSN = #kNoProcess
2. All Cocoa (take a look at the NSRunningApplication Class Reference for more information)

Code: Select all

RunningApps = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "runningApplications")
RunningAppsCount = CocoaMessage(0, RunningApps, "count")

i = 0
While i < RunningAppsCount
  
  RunningApp = CocoaMessage(0, RunningApps, "objectAtIndex:", i)
  PID.i = CocoaMessage(0, RunningApp, "processIdentifier")
  AppName.s = PeekS(CocoaMessage(0, CocoaMessage(0, RunningApp, "localizedName"), "UTF8String"), -1, #PB_UTF8)
  If CocoaMessage(0, RunningApp, "isActive")
    AppName + "  ** Active **"
  EndIf
  Debug "PID = " + Str(PID) + ": " + AppName
  
  i + 1
Wend
3. Cocoa but presented a bit nicer

Code: Select all

RunningApps = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "runningApplications")
RunningAppsCount = CocoaMessage(0, RunningApps, "count")

OpenWindow(0, 100, 100, 600, 400, "Running applications", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListIconGadget(0, 10, 10, 580, 380, "PID", 60, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_CheckBoxes)
AddGadgetColumn(0, 1, "Name", 400)

Define i = 0
While i < RunningAppsCount
  
  RunningApp = CocoaMessage(0, RunningApps, "objectAtIndex:", i)
  PID.i = CocoaMessage(0, RunningApp, "processIdentifier")
  AppName.s = PeekS(CocoaMessage(0, CocoaMessage(0, RunningApp, "localizedName"), "UTF8String"), -1, #PB_UTF8)
  AddGadgetItem(0, i, Str(PID) + #LF$ + AppName)
  SetGadgetItemImage(0, i, CocoaMessage(0, RunningApp, "icon"))
  If CocoaMessage(0, RunningApp, "isActive")
    SetGadgetItemState(0, i, #PB_ListIcon_Checked)
  EndIf
  
  i + 1
Wend

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Carbon API list for Mac

Post by Keya »

Many thanks wilbert! All those examples work beautifully on my Mac64 :)
Im getting two programming books on Mac in a week or two both go into Cocoa so hopefully I won't have to ask too many stupid questions for long heehe
Reading the documentation as you suggested for NSRunningApplication Class i see that we need to check "executableURL" to get the actual path of the process, it's of type "NSURL" not string like "localizedName", how can we read that? My searched showed a couple other NSURL purebasic uses but i couldnt get it working with this, usually memory error saying incompatible type :(
ps. (no pun!) even when I run it with sudo it only lists about a quarter of the ones that "ps -x" lists?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Carbon API list for Mac

Post by wilbert »

URL can be done like this

Code: Select all

RunningApps = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "runningApplications")
RunningAppsCount = CocoaMessage(0, RunningApps, "count")

OpenWindow(0, 100, 100, 600, 400, "Running applications", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListIconGadget(0, 10, 10, 580, 380, "PID", 60, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_CheckBoxes)
AddGadgetColumn(0, 1, "Name", 280)
AddGadgetColumn(0, 2, "Executable", 1500)

Define i = 0
While i < RunningAppsCount
  
  RunningApp = CocoaMessage(0, RunningApps, "objectAtIndex:", i)
  PID.i = CocoaMessage(0, RunningApp, "processIdentifier")
  AppName.s = PeekS(CocoaMessage(0, CocoaMessage(0, RunningApp, "localizedName"), "UTF8String"), -1, #PB_UTF8)
  ExecutableURL.i = CocoaMessage(0, CocoaMessage(0, RunningApp, "executableURL"), "absoluteString")
  URL.s = PeekS(CocoaMessage(0, ExecutableURL, "UTF8String"), -1, #PB_UTF8)
  AddGadgetItem(0, i, Str(PID) + #LF$ + AppName + #LF$ + URL)
  SetGadgetItemImage(0, i, CocoaMessage(0, RunningApp, "icon"))
  If CocoaMessage(0, RunningApp, "isActive")
    SetGadgetItemState(0, i, #PB_ListIcon_Checked)
  EndIf
  
  i + 1
Wend

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
As for the difference with "ps -x", you are right.
I suppose those other items are not applications or owned by 'root' but am not sure.
You can show more processes another way but unfortunately the name of the process is truncated to the first 16 characters

Code: Select all

ImportC ""
  proc_listallpids(*buffer, buffersize)
  proc_name(pid, *buffer, buffersize)
  proc_pidpath(pid, *buffer, buffersize)
EndImport

cnt = proc_listallpids(#Null, 0)
Dim PID.l(cnt - 1)
cnt = proc_listallpids(@PID(), cnt << 2) 
ReDim PID(cnt - 1)

Dim buffer.a(1024)

For i = 0 To cnt - 1
  Debug PeekS(@Buffer(), proc_name(PID(i), @buffer(), 1024), #PB_Ascii)    
  Debug PeekS(@Buffer(), proc_pidpath(PID(i), @buffer(), 1024), #PB_Ascii) 
  Debug ""
Next
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Carbon API list for Mac

Post by Keya »

Thankyou! :) hmm well NSURL turned out a little different than i thought, lol :)

btw yes my searching has found at least two ways!
proc_listpids as youve just shown,
and also GetBSDProcessList function:

Code: Select all

int main(int argc, char *argv[]) {
  kinfo_proc *procs;
  size_t count;
  int err = GetBSDProcessList(&procs, &count);
  if (err) return err;
  FILE *f = fopen("./bsdlist", "w");
  for (size_t i=0; i!=count; ++i) {
    fprintf(f, "%d\n", procs[i].kp_proc.p_pid);
  }
  fclose(f);
  free(procs);
}
looking into kinfo_proc...
Last edited by Keya on Wed Aug 26, 2015 8:57 am, edited 1 time in total.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Carbon API list for Mac

Post by wilbert »

I couldn't get GetBSDProcessList to work; didn't know the import location. :?

Edit:
I moved my code example to the Cocoa thread since it has little to do with Carbon
http://www.purebasic.fr/english/viewtop ... 87#p469687
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply