Prefazione
Questa guida è stata scritta da Andrea Azzarone, su forum arlecchino92. Una discussione relativa a questa guida si trova a questo indirizzo http://forum.ubuntu-it.org/viewtopic.php?t=449834 La guida sarà pubblicata a puntate ogni volta che ne sarà disponibile una nuova.
Introduzione
Prerequisiti e linguaggi di programmazione
Sicuramente non è una guida rivolta a tutti gli utenti di Ubuntu, ma non sono richieste capacità eccezionali nell' arte della programmazione! Prima di tutto Unity è scritto per la maggior parte in C++, sebbene alcune parti siano scritte in C o in Vala. Sottolineare che questa guida si riferisce alla versione in sviluppo di Ubuntu Natty Narwhal 11.04. Unity utilizza inoltre il toolkit grafico nux e le librerie gnome.
Bug e bitsize
La lista dei bug di Unity è disponibile qui: https://bugs.launchpad.net/unity Ma c'è un piccolo problema con questi ultimi! La maggior parte sono abbastanza ostici da risolvere e richiedono già maggiore esperienza. Niente paura, il team di Unity ha già pensato a questo. È stata creata una lista di bug minori, che richiedono minori competenze, e che attutirà l'impatto con il codice di Unity. La lista dei bug minori (bitsize) è disponibile qui.
Per voi ho scelto di realizzare qualcosa di abbastanza interessante: cercheremo di aggiungere alla quicklist dei vari dispositivi la voce "Unmount".
Compilare e installare unity da codice sorgente
Ricordo ancora una volta che è necessario utilizzare Ubuntu Natty! Cominciamo installando un po' di roba che ci servirà in seguito. Da terminale:
sudo apt-get install bzr cmake compiz-dev gnome-common libbamf-dev libboost-dev libboost-serialization-dev libcairo2-dev libdbusmenu-glib-dev libdee-dev libgconf2-dev libgdk-pixbuf2.0-dev libglew1.5-dev libglewmx1.5-dev libglib2.0-dev libindicator-dev libpango1.0-dev libpcre3-dev libsigc++-2.0-dev libunity-misc-dev libutouch-geis-dev
Come già detto in precedenza Unity utilizza il toolkit grafico nux, che è ancora in sviluppo. È possibile installarlo direttamente da repository ma se davvero volete cominciare a "modificare e implementare nuove funzioni in Unity" dovremo prima di tutto compilare nux da sorgenti! Quindi da terminale:
bzr branch lp:nux cd nux ./autogen.sh --disable-documentation --prefix=/opt/unity make -j4 sudo make install
e successivamente:
export PKG_CONFIG_PATH=/opt/unity/lib/pkgconfig:${PKG_CONFIG_PATH} export LD_LIBRARY_PATH=/opt/unity/lib:${LD_LIBRARY_PATH} export LD_RUN_PATH=/opt/unity/lib:${LD_RUN_PATH}
che installerà Unity in /opt/unity. Procediamo adesso alla compilazione e installazione vera e propria di Unity:
bzr branch lp:unity cd unity mkdir build; cd build cmake .. -DCMAKE_BUILD_TYPE=Debug -DCOMPIZ_PLUGIN_INSTALL_TYPE=local -DCMAKE_INSTALL_PREFIX=/opt/unity make -j4 sudo make install sudo mkdir /opt/unity/share/unity/places sudo cp /usr/share/unity/places/* /opt/unity/share/unity/places/
Il codice si commenta da solo Maggiori info sono comunque disponibili qui. E ancora:
unset PKG_CONFIG_PATH unset LD_LIBRARY_PATH unset LD_RUN_PATH
Editiamo adesso il file ~/.bashrc:
gedit ~/.bashrc
aggiungendo le seguenti 4 righe alla fine del file:
function compiz-unity-setup-env { export PATH=/opt/unity/bin:${PATH} } }} Adesso non ci resta che effettuare il log out e il log in, e lanciare da terminale i seguenti comandi: {{{ compiz-unity-setup-env compiz --replace
La guida originale alla compilazione è stata scritta da Stefano Candori e la si può trovare qui
Una prima occhiata al codice
Se avete seguito correttamente le istruzioni nella vostra home avrete i sorgenti di Unity. Diamo un'occhiata alla struttura generale:
AUTHORS COPYING.LGPL src build doc tests ChangeLog INSTALL tools cmake plugin-unityshell.png unity-private CMakeLists.txt po unityshell.xml.in com.canonical.Unity.gschema.xml README utouch config.h.cmake resources vapi COPYING services
Per il momento analizziamo tre voci:
src unityshell.xml.in com.canonical.Unity.gschema.xml
Come forse avrete già intuito src sta per "source" ovverso "codice sorgente". Vediamo cosa contiene al momento (in futuro potrebbe cambiare qualcosa):
BamfLauncherIcon.cpp PlaceLauncherIcon.h BamfLauncherIcon.h PlaceLauncherSection.cpp DebugDBusInterface.cpp PlaceLauncherSection.h DebugDBusInterface.h PlaceRemote.cpp DeviceLauncherIcon.cpp PlaceRemote.h DeviceLauncherIcon.h PlacesController.cpp DeviceLauncherSection.cpp PlacesController.h DeviceLauncherSection.h PlacesGroupController.cpp DevicesSettings.cpp PlacesGroupController.h DevicesSettings.h PlacesGroup.cpp FavoriteStore.cpp PlacesGroup.h FavoriteStoreGSettings.cpp PlacesHomeView.cpp FavoriteStoreGSettings.h PlacesHomeView.h FavoriteStore.h PlacesResultsController.cpp GeisAdapter.cpp PlacesResultsController.h GeisAdapter.h PlacesResultsView.cpp GestureEngine.cpp PlacesResultsView.h GestureEngine.h PlacesSearchBar.cpp IconLoader.cpp PlacesSearchBar.h IconLoader.h PlacesSettings.cpp IconTexture.cpp PlacesSettings.h IconTexture.h PlacesSimpleTile.cpp IndicatorObjectEntryProxy.h PlacesSimpleTile.h IndicatorObjectEntryProxyRemote.cpp PlacesStyle.cpp IndicatorObjectEntryProxyRemote.h PlacesStyle.h IndicatorObjectFactory.h PlacesTile.cpp IndicatorObjectFactoryRemote.cpp PlacesTile.h IndicatorObjectFactoryRemote.h PlacesView.cpp IndicatorObjectProxy.h PlacesView.h IndicatorObjectProxyRemote.cpp PluginAdapter.cpp IndicatorObjectProxyRemote.h PluginAdapter.h Introspectable.cpp QuicklistManager.cpp Introspectable.h QuicklistManager.h LauncherController.cpp QuicklistMenuItemCheckmark.cpp LauncherController.h QuicklistMenuItemCheckmark.h Launcher.cpp QuicklistMenuItem.cpp LauncherDragWindow.cpp QuicklistMenuItem.h LauncherDragWindow.h QuicklistMenuItemLabel.cpp LauncherEntryRemote.cpp QuicklistMenuItemLabel.h LauncherEntryRemote.h QuicklistMenuItemRadio.cpp LauncherEntryRemoteModel.cpp QuicklistMenuItemRadio.h LauncherEntryRemoteModel.h QuicklistMenuItemSeparator.cpp Launcher.h QuicklistMenuItemSeparator.h LauncherIcon.cpp QuicklistView.cpp LauncherIcon.h QuicklistView.h LauncherModel.cpp SimpleLauncherIcon.cpp LauncherModel.h SimpleLauncherIcon.h nux-area-accessible.cpp SpacerLauncherIcon.cpp nux-area-accessible.h SpacerLauncherIcon.h nux-base-window-accessible.cpp StartupNotifyService.cpp nux-base-window-accessible.h StartupNotifyService.h nux-layout-accessible.cpp StaticCairoText.cpp nux-layout-accessible.h StaticCairoText.h nux-object-accessible.cpp TextureCache.cpp nux-object-accessible.h TextureCache.h nux-view-accessible.cpp TimeMe.cpp nux-view-accessible.h TimeMe.h PanelHomeButton.cpp Tooltip.cpp PanelHomeButton.h Tooltip.h PanelIndicatorObjectEntryView.cpp TrashLauncherIcon.cpp PanelIndicatorObjectEntryView.h TrashLauncherIcon.h PanelIndicatorObjectView.cpp UBusMessages.h PanelIndicatorObjectView.h ubus-server.cpp PanelMenuView.cpp ubus-server.h PanelMenuView.h unitya11y.cpp PanelStyle.cpp unitya11y.h PanelStyle.h unitya11ytests.cpp PanelTitlebarGrabAreaView.cpp unitya11ytests.h PanelTitlebarGrabAreaView.h unity-launcher-accessible.cpp PanelTray.cpp unity-launcher-accessible.h PanelTray.h unity-launcher-icon-accessible.cpp PanelView.cpp unity-launcher-icon-accessible.h PanelView.h unity-panel-home-button-accessible.cpp perf-logger-utility.h unity-panel-home-button-accessible.h perf-logger.vala unity-panel-view-accessible.cpp PlaceEntry.h unity-panel-view-accessible.h PlaceEntryHome.cpp unity-root-accessible.cpp PlaceEntryHome.h unity-root-accessible.h PlaceEntryRemote.cpp unityshell.cpp PlaceEntryRemote.h unityshell.h PlaceFactory.cpp unity-util-accessible.cpp PlaceFactoryFile.cpp unity-util-accessible.h PlaceFactoryFile.h WindowButtons.cpp PlaceFactory.h WindowButtons.h Place.h WindowManager.cpp PlaceLauncherIcon.cpp WindowManager.h
Non vi spaventate, in realtà tranne per la parte puramente grafica (che sfrutta le librerie nux e quindi le opengl) il codice è abbastanza pulito e di facile comprensione. Ad sempio poichè andremo ad aggiungere la voce "Unmount" alla quicklist delle icone dei dispositivi/partizioni sul launcher per intuito probabilmente dovremo operare sul file DeviceLauncherIcon.cpp e il suo header DeviceLauncherIcon.h. Se l'intuito non basta può aiutarci il terminale... Sappiamo che nella quicklist di un dispositivo rimovibile (ad es. una pendrive usb) è prensete la voce "Safely Remove". Da terminale diamo:
grep "Safely Remove" ~//unity/src/*
e per magia:
/home/andrea/unity/src/DeviceLauncherIcon.cpp: dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Safely Remove")); Non esiste un metodo universale per individuare in quale parte del codice andare ad operare (per il momento sorvoliamo di risolvere i crash per i quali gdb è di immenso aiuto), ma un buon intuito e l'utilizzo del terminale dovrebbero bastare Passiamo alla seconda voce che volevo farvi notare, ovvero unityshell.xml.in. Uno sguardo al file e probabilmente capirete prima che ve lo dica esplicitamente: {{{ <?xml version="1.0" encoding="UTF-8"?> <compiz> <plugin name="unityshell" useBcop="true"> <_short>Ubuntu Unity Plugin</_short> <_long>Plugin to draw the Unity Shell</_long> <category>Desktop</category> <deps> <relation type="after"> <plugin>bailer</plugin> <plugin>detection</plugin> <plugin>composite</plugin> <plugin>opengl</plugin> <plugin>mousepoll</plugin> <plugin>move</plugin> <plugin>resize</plugin> <plugin>decor</plugin> <plugin>compiztoolbox</plugin> <plugin>place</plugin> <plugin>session</plugin> <plugin>animation</plugin> <plugin>regex</plugin> <plugin>cube</plugin> <plugin>rotate</plugin> <plugin>cubeaddon</plugin> <plugin>gnomecompat</plugin> <plugin>vpswitch</plugin> <plugin>fade</plugin> <plugin>staticswitcher</plugin> <plugin>scale</plugin> <plugin>expo</plugin> <plugin>ezoom</plugin> <plugin>wall</plugin> </relation> <requirement> <plugin>opengl</plugin> <plugin>wall</plugin> </requirement> </deps> <options> <group> <_short>Behaviour</_short> <option name="launcher_hide_mode" type="int"> <_short>Hide Launcher</_short> <_long>Make the launcher hide automatically after some time of inactivity: always or just when the focussed window is not over the launcher</_long> <min>0</min> <max>3</max> <default>2</default> <desc> <value>0</value> <_name>Never</_name> </desc> <desc> <value>1</value> <_name>Autohide</_name> </desc> <desc> <value>2</value> <_name>Dodge Windows</_name> </desc> <desc> <value>3</value> <_name>Dodge Active Window</_name> </desc> </option> <option name="show_launcher" type="key"> <_short>Key to show the launcher</_short> <_long>Make the launcher appear with that key</_long> <default><Super></default> </option> <option name="keyboard_focus" type="key"> <_short>Key to put keyboard-focus on launcher</_short> <_long>Set the keyboard-focus on the launcher so it can be navigated with the cursor-keys</_long> <default><Alt>F1</default> </option> <option name="execute_command" type="key"> <_short>Key to execute a command</_short> <_long>Key to open a folder or execute a command</_long> <default><Alt>F2</default> </option> <option name="panel_first_menu" type="key"> <_short>Key to open the first panel menu</_short> <_long>Open the first menu on the panel, allowing keyboard navigation thereafter.</_long> <default>F10</default> </option> </group> <group> <_short>Experimental</_short> <option name="backlight_mode" type="int"> <_short>Backlight Mode</_short> <_long>Change how the icons are backlit</_long> <min>0</min> <max>2</max> <default>0</default> <desc> <value>0</value> <_name>Backlight Always On</_name> </desc> <desc> <value>1</value> <_name>Backlight Toggles</_name> </desc> <desc> <value>2</value> <_name>Backlight Always Off</_name> </desc> </option> <option name="launch_animation" type="int"> <_short>Launch Animation</_short> <_long>Animation played when a launcher icon is in the process of spawning a process</_long> <min>0</min> <max>2</max> <default>1</default> <desc> <value>0</value> <_name>None</_name> </desc> <desc> <value>1</value> <_name>Pulse Until Running</_name> </desc> <desc> <value>2</value> <_name>Blink</_name> </desc> </option> <option name="urgent_animation" type="int"> <_short>Urgent Animation</_short> <_long>Animation played when a launcher icon is in the urgent state</_long> <min>0</min> <max>2</max> <default>2</default> <desc> <value>0</value> <_name>None</_name> </desc> <desc> <value>1</value> <_name>Pulse</_name> </desc> <desc> <value>2</value> <_name>Wiggle</_name> </desc> </option> <option type="float" name="panel_opacity"> <_short>Panel Opacity</_short> <_long>The opacity of the Panel background.</_long> <default>1.0</default> <min>0.0</min> <max>1.0</max> <precision>0.01</precision> </option> <option name="icon_size" type="int"> <_short>Launcher icon size</_short> <_long>The size of the launcher icons</_long> <default>48</default> <min>32</min> <max>64</max> <precision>1</precision> </option> <option name="autohide_animation" type="int"> <_short>Hide Animation</_short> <_long>Animation played when the launcher is showing or hiding</_long> <min>0</min> <max>2</max> <default>0</default> <desc> <value>0</value> <_name>Fade on bfb and Slide</_name> </desc> <desc> <value>1</value> <_name>Slide only</_name> </desc> <desc> <value>2</value> <_name>Fade only</_name> </desc> </option> <option name="dash_blur_experimental" type="int"> <_short>Dash Blur</_short> <_long>Type of blur in the Dash</_long> <min>0</min> <max>1</max> <default>0</default> <desc> <value>0</value> <_name>No Blur</_name> </desc> <desc> <value>1</value> <_name>Static Blur</_name> </desc> </option> </group> </options> </plugin> </compiz>
Beh se non ci siete arrivati, questo è in linea di massima il file utilizzato dal ccsm per inserire le varie opzioni di configurazione (sebbene serva anche ad altro!). Non mi stancherò mai di ripeterlo: Unity è un plugin di compiz! Ad esempio quando qualche giorno ho voluto aggiungere l'opzione per scegliere quali dispositivi visualizziare ho aggiunto questa sezione al file:
<option name="devices_option" type="int"> <_short>Show Devices</_short> <_long>Show Devices in the Springboad</_long> <min>0</min> <max>2</max> <default>1</default> <desc> <value>0</value> <_name>Never</_name> </desc> <desc> <value>1</value> <_name>Only Mounted</_name> </desc> <desc> <value>2</value> <_name>Always</_name> </desc> </option>
L'ultimo file che andremo ad analizzare è com.canonical.Unity.gschema.xml. I lettori più attenti probabilmente avranno capito che si tratta del file in cui sono dichiarate le varie chiavi gsettings (maggiori info qui).
Per il momento può bastare la prima occhiata al codice!
Cominciamo a modificare il codice...
Se ben ricordate avevamo già individuato qualche giorno fa quali file modificare: DeviceLauncherIcon.cpp e naturalmente il suo file headerDeviceLauncherIcon.h La prima cosa da fare è dare un'occhiata generale al codice cercando di capire a cosa servono le funzioni... in questa prima fase non sarà necessario entrare nel dettaglio. Questa fase ci viene facilitata dagli stessi autori di Unity che generalmente utilizzando nomi di funzioni abbastanza esplicativi. Non bisogna essere chissa chi per capire che la funzione OnMouseClick è la funzione associata al click del mouse sull'icona... Diamo un'occhiata alla funzione che più ci riguarda:
std::list<DbusmenuMenuitem *> DeviceLauncherIcon::GetMenus () { std::list<DbusmenuMenuitem *> result; DbusmenuMenuitem *menu_item; GDrive *drive; menu_item = dbusmenu_menuitem_new (); dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Open")); dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); g_signal_connect (menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (&DeviceLauncherIcon::OnOpen), this); result.push_back (menu_item); if (g_volume_can_eject (_volume)) { menu_item = dbusmenu_menuitem_new (); dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Eject")); dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); g_signal_connect (menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (&DeviceLauncherIcon::OnEject), this); result.push_back (menu_item); } drive = g_volume_get_drive (_volume); if (drive && g_drive_can_stop (drive)) { menu_item = dbusmenu_menuitem_new (); dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Safely Remove")); dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); g_signal_connect (menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (&DeviceLauncherIcon::OnDriveStop), this); result.push_back (menu_item); g_object_unref (drive); } return result; }