Home How to differentiate two identical Smalltalk/X-jv instances?
Post
Cancel

How to differentiate two identical Smalltalk/X-jv instances?

Having two instances of Smalltalk/X is a great idea I got from Jan Vraný. If you do so, you can debug at one instance and in the second one you can continue developing.

This guide shows you how to have two same instances differentiated in Linux Gnome shell in a way you don’t confuse them between each other.

Gnome-Shell based instance differentiation

Different SVG icons

First what comes into mind is to have different icons for each instance. I have used the icon distributed with Smalltalk/X and added a number for each instance. I have placed the custom icons to the path: /usr/share/icons/hicolor/scalable/apps/.

The svg instances icons:

First instance svg iconThe first instance svg icon

Second instance svg iconThe second instance svg icon

Different window class the WM_CLASS property

Next is for the Gnome to be able to differentiate between each instance. This was tricky and took some time of playing around even with D-Bus. Which led to creation of article about terminal mc terminal application being able to run as GUI application.

The best solution in my eyes is using the WM_CLASS property. The definition is taken from the link:

The WM_CLASS property (of type STRING without control characters) contains two consecutive null-terminated strings. These specify the Instance and Class names to be used by both the client and the window manager for looking up resources for the application or as identifying information. This property must be present when the window leaves the Withdrawn state and may be changed only while the window is in the Withdrawn state. Window managers may examine the property only when they start up and when the window leaves the Withdrawn state, but there should be no need for a client to change its state dynamically.

The two strings, respectively, are:

  • A string that names the particular instance of the application to which the client that owns this window belongs. Resources that are specified by instance name override any resources that are specified by class name. Instance names can be specified by the user in an operating-system specific manner. On POSIX-conformant systems, the following conventions are used:
    • If “-name NAME” is given on the command line, NAME is used as the instance name.
    • Otherwise, if the environment variable RESOURCE_NAME is set, its value will be used as the instance name.
    • Otherwise, the trailing part of the name used to invoke the program (argv[0] stripped of any directory names) is used as the instance name.
  • A string that names the general class of applications to which the client that owns this window belongs. Resources that are specified by class apply to all applications that have the same class name. Class names are specified by the application writer. Examples of commonly used class names include: “Emacs”, “XTerm”, “XClock”, “XLoad”, and so on.

Note that WM_CLASS strings are null-terminated and, thus, differ from the general conventions that STRING properties are null-separated. This inconsistency is necessary for backwards compatibility.

How to set or read the WM_CLASS property in your code visit - 14.1.8 Setting and Reading the WM_CLASS Property

Setting WM_CLASS property at Smalltalk/X

The Smalltalk/X works with the WM_CLASS property in the XWorkstation>>initializeDefaultValues. The WM_CLASS is read into Smalltalk/X via environment variable RESOURCE_NAME. If you export the RESOURCE_NAME before running the Smalltalk/X you will be able to differentiate the instances from each other.

Here is the excerpt of the XWorkstation>>initializeDefaultValues code which defines the wmClassName:

XWorkstation>>initializeDefaultValues

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
    "
    Create (and cache) class and name for WM_CLASS property. 
    (defined by ICCCM, Section 4.1.2.5. WM_CLASS Property)
    "
    wmClassName := OperatingSystem getEnvironment: 'RESOURCE_NAME'.
    wmClassName isNil ifTrue:[
        wmClassName := Smalltalk commandName.
        "strip of any directory names"
        wmClassName := wmClassName copyFrom: (wmClassName lastIndexOf: Filename separator) + 1.
    ].
    (wmClassName = 'stx' or:[wmClassName = 'stx-bin']) ifTrue:[
        wmClassName  := 'smalltalkx'.
        wmClassClass := 'SmalltalkX'.
    ] ifFalse:[
        wmClassClass := wmClassName asUppercaseFirst.
    ].
...
  • To export the variable before running Smalltalk/X while not having it permanently in the environment, the smalltalk bash launcher has to be edited at path: ~/smalltalkx/build/stx/projects/smalltalk/smalltalk.

  • To export the variable you have to do add this to the launcher bash script (at the second instance):
    1
    
    export RESOURCE_NAME="SmalltalkX-2nd"
    
  • Last but not the least, you have to edit the .desktop file at ~/.local/share/applications/. The desktop file must contain the StartupWMClass=SmalltalkX-2nd which identifies the the seconds instance for Gnome Shell. I recommend adding the StartupWMClass also to the first instance as StartupWMClass=SmalltalkX (which is hard-coded as default WM_CLASS for Smalltalk/X).

The complete first instance desktop file:

1
2
3
4
5
6
7
8
9
[Desktop Entry]
Name=First Smalltalk/X
Comment=Smalltalk IDE
Exec="/home/tukan/Prg_sdk/1st-stx8-jv/build/stx/projects/smalltalk/smalltalk" --quick
Icon=smalltalkx-first
Type=Application
Keywords=Smalltalk;IDE;Development
StartupWMClass=SmalltalkX
Terminal=false

The complete second instance desktop file:

1
2
3
4
5
6
7
8
9
10
[Desktop Entry]
Name=Second Smalltalk/X
Comment=Smalltalk IDE
Exec="/home/tukan/Prg_sdk/2nd-stx8-jv/build/stx/projects/smalltalk/smalltalk" --quick
Icon=smalltalkx-second
Type=Application
Keywords=Smalltalk;IDE;Development
StartupWMClass=SmalltalkX-2nd
StartupNotify=true
Terminal=false

If a gnome terminal window should be started with Smalltalk/X, the Terminal=true needs to be set. Note: this terminal window will not be listed among other terminal windows.

The only disadvantage, I have noticed, when using WM_CLASS property is that the Gnome Shell tab switcher takes some time (up to few seconds) to register (list it among other applications) the second Smalltalk/X instance (which is using the changed RESOURCE_NAME). The Gnome’s dash, on the other hand, registers it instantly.

The Smalltalk/X based instance differentiation

I have created patch which will hopefully end up in the Smalltalk/X-jv soon. It exposes two menuPanel color variables menu_bg_color and menu_fg_color to the Adwaita style file, which enables anyone who wants to customize the menu color to their liking.

The Adwaita style file is to be found at ~/smalltalkx/build/stx/libview/styles/Adwaita_colors.style. There are two variants light and dark, which have their own set of variables set. I’m using dark scheme at Smalltalk/X so I’ll be changing only the dark part only.

The @Adwaita_colors.style file customization (the default values):

1
2
3
4
5
6
7
8
9
10
#if $variant = 'light'
...
menu_bg_color                            Color rgbValue: 16rf6f5f4
menu_fg_color                            Color rgbValue: 16r2e3436
...
#else //variant = 'dark'
...
menu_bg_color                            Color rgbValue: 16r353535
menu_fg_color                            Color rgbValue: 16reeeeec
...

The only changed value is enough for me:

1
2
3
4
5
6
7
#else //variant = 'dark'
...
; second instance menuPanel color
menu_bg_color                            Color rgbValue: 16r19334c
; the fg is the same for the 2nd instance
menu_fg_color                            Color rgbValue: 16reeeeec
...

How does the result look like?

Here is a screenshot

Two Smalltalk/X instancesTwo differentiated Smalltalk/X instances

Conclusion

For myself, I must say I’m really happy with the result. After this change I have never mistaken one Smalltalk/X instance for the other.

Note: In this blog I’m using Smalltalk/x-jv branch, which is maintained by Jan Vraný. The upstream Smalltalk/X was created and build by Claus Gittinger. It is used in products developed by the eXept company.

This post is licensed under CC BY 4.0 by the author.