Welcome to the Linux Foundation Forum!

Changing a text cursor in GNOME

Hi.

Is it possible to change a color of the text cursor for all GUI applications in GNOME? If it is, how can I achieve it?

Thanks.

Comments

  • jabirali
    jabirali Posts: 157
    Create the file /home/username/.gtkrc-2.0 , and add the following text to it:
    style "custom" {
    GtkWidget::cursor-color    = "#FF0000"
    GtkWidget::secondary-cursor-color = "#FF0000"
    }
    
    widget_class "*" style "custom"
    
    After saving, logging out and logging in again, all GTK2 applications (including all gnome applications, and gimp, firefox, etc) should use the cursor color #FF0000, which is pure red. If you don't know how to find the hexadecimal color code you want, install the application gcolor2 to help you out.
  • E_force
    E_force Posts: 10
    Can I change it dynamically depending on, for example, the currently keyboard layout?
  • jabirali
    jabirali Posts: 157
    If it's possible, I'm afraid it's beyond my knowledge.

    If all you want is a way to keep track of what keyboard layout you're currently using, enabling multiple keyboard layouts in System -> Preferences -> Keyboard -> Layouts should add a keyboard layout indicator to the system tray on your panel.
  • E_force
    E_force Posts: 10
    Thanks for the help, Jabir.

    My point is to improve my experience working with multiple layouts. When you type you usually look at the text cursor thus there's no better way to show the current layout as setting an indicator right before your eyes.
  • jabirali
    jabirali Posts: 157
    Actually, after a bit of googling, it seems like it might be possible after all.

    I found this python script on the interwebs, which makes all GTK2 applications reload the current settings in ~/.gtkrc-2.0:
    #!/usr/bin/python
    import pygtk
    import gtk
    events=gtk.gdk.Event(gtk.gdk.CLIENT_EVENT)
    data=gtk.gdk.atom_intern("_GTK_READ_RCFILES", True)
    events.data_format=8
    events.send_event=True
    events.message_type=data
    events.send_clientmessage_toall()
    

    After a few modifications of my own, I ended up with the following script:
    #!/usr/bin/python
    import pygtk, gtk, os
    
    keyboard1="us"
    keyboard2="no"
    
    os.chdir(os.path.abspath(os.environ['HOME']))
    if os.readlink(".gtkrc-2.0") == ".gtkrc-custom-1":
            print "Switching to layout 2"
            os.remove(".gtkrc-2.0")
            os.symlink(".gtkrc-custom-2", ".gtkrc-2.0")
            os.system("setxkbmap " + keyboard2)
    else:
            print "Switching to layout 1"
            os.remove(".gtkrc-2.0")
            os.symlink(".gtkrc-custom-1", ".gtkrc-2.0")
            os.system("setxkbmap " + keyboard1)
    
    
    events=gtk.gdk.Event(gtk.gdk.CLIENT_EVENT)
    data=gtk.gdk.atom_intern("_GTK_READ_RCFILES", False)
    events.data_format=8
    events.send_event=True
    events.message_type=data
    events.send_clientmessage_toall()
    
    The variables keyboard1 and keyboard2 at the top should be set to two different keyboard maps; in my case, us for american and no for norwegian.

    You should also have two styling files, ~/.gtkrc-custom-1:
    style "custom" { 
    GtkWidget::cursor-color    = "#FF0000" 
    GtkWidget::secondary-cursor-color = "#FF0000" 
    } 
     
    widget_class "*" style "custom"
    
    and ~/.gtkrc-custom-2:
    style "custom" { 
    GtkWidget::cursor-color    = "#00FF00" 
    GtkWidget::secondary-cursor-color = "#00FF00" 
    } 
     
    widget_class "*" style "custom"
    

    And make ~/.gtkrc-2.0 a symlink to ~/.gtkrc-custom-1:
    ln -sf ~/.gtkrc-custom-1 ~/.gtkrc-2.0
    

    The concept is then simple. The script checks if the file ~/.gtkrc-2.0 points to ~/.gtkrc-custom-1 (red cursor), and in that case changes the link to point to ~/.gtkrc-custom-2 (green cursor) and at the same time switches keyboard map to keyboard2. If ~/.gtkrc-2.0 does not point to ~/.gtkrc-custom-1, it switches to ~/.gtkrc-custom-1 and sets keyboard map keyboard1.

    The only thing you have to do, is map the script to a keyboard shortcut, and it should handle both switching of cursor color and keymap for you. (A cleaner solution might have been to use a script that calls gtk.rc_parse_string() instead of reloading gtkrc, but I'm not familiar enough with pygtk to get that working...)

    Hope this helps :P
  • jabirali
    jabirali Posts: 157
    In case you don't know how to add keyboard shortcuts for custom applications in Gnome, I should perhaps add that too.

    First, you have to install gconf-editor with the package management tool of your distribution. Then, press Alt+F2 and enter gconf-editor into the popup dialog.

    In the application that shows up, browse to /apps/metacity/keybinding_commands in the left pane. In the right pane, set command_1 to python /path/to/script.py.

    Then go to /apps/metacity/global_keybindings in the left pane, and edit run_command_1 in the right pane to the desired keyboard shortcut; e.g. to use Ctrl+Shift+F12 to run the script, make it:
    <Ctrl><Shift>F12
    
  • E_force
    E_force Posts: 10
    Interesting approach but how about to base the script on some variable which contains the current layout or some method which returns it? This variable or method should exist in the system. Otherwise, how the GNOME's keyboard applet would determine the layout.

    Here's how it would work.
    case system('echo $CURR_LAYOUT') # or ENV['CURR_LAYOUT'] or curr_layout() or smth.
    when 'us' then symlink('~/.gtkrc-custom-1', '~/.gtkrc-2.0')
    when 'ru' then symlink('~/.gtkrc-custom-2', '~/.gtkrc-2.0')
    else symlink('~/.gtkrc-custom-default', '~/.gtkrc-2.0')
    end
    
    What do you think about it?
  • jabirali
    jabirali Posts: 157
    That might be a superior solution :)

    The only way I know to get this piece of information, would be to parse the output of the command setxkbmap -v. One of the output lines should start with either symbols: pc+us+inet or symbols: pc+ru+inet.

    Note that the keymap should still be set by calling e.g. setxkbmap ru from within the script. Although it would be possible to first use your old method of switching keyboard layout, and then run the script - automating this would require either (1) running the script periodically or (2) daemonizing it and watch e.g. Xorg.0.log for changes... Both of these alternatives would be a bit overkill - at least in my humble opinion.

    [edit]
    I just stumbled over a project called python-xkb - I haven't tried it out, but I suspect it might provide a more pythonian way of checking and switching keyboard layout. If you have some free time, perhaps it isn't that far fetched to make a PyGTK systray application that waits for XKB events and changes GTK2 settings accordingly :)
  • E_force
    E_force Posts: 10
    After about an hour of coding I get a simple application which changes the cursor's color according to the layout. I used two third party scripts: your Python script which reloads GTK settings and the xkblayout application written on the C language which returns the current keyboard layout. I combined this two in my own Ruby script which checks the current layout, changes the style of the text cursor and reloads settings for all of the opened applications. Yet it can only work with GTK applications but I would like to enable Qt and the console support.

    The application has a simple structure.
    layout_indicator/
      - reload_gtk_settings.py # a Python script
      - show_the_current_layout # a C script
      - switch_layout_style.rb # a Ruby scirpt
    

    To enable this application to work you should have Python and Ruby installed. You should also create a bunch of GTK configuration files.

    First you need to create ~/.gtkrc-2.0: touch ~/.gtkrc-2.0.

    The file should contain a single line.
    include ".gtkrc-custom"
    

    Second you need to to create ~/.gtkrc-custom-us, ~/.gtkrc-custom-<your_language> and ~/.gtk-custom-default: touch ~/.gtkrc-custom-us ~/.gtkrc-custom-<your_language> ~/.gtk-custom-default.

    They should contain the following.

    ~/.gtk-custom-us
    style "custom" {
      GtkWidget::cursor-color           = "#0000FF"
      GtkWidget::secondary-cursor-color = "#0000FF"
    }
    
    widget_class "*" style "custom"
    

    This style specifies the blue color for the en-us layout.

    ~/.gtk-custom-<your-language>
    style "custom" {
      GtkWidget::cursor-color           = "#FF0000"
      GtkWidget::secondary-cursor-color = "#FF0000"
    }
    
    widget_class "*" style "custom"
    

    This style specifies the red color for your layout.

    ~/.gtk-custom-default
    style "custom" {
      GtkWidget::cursor-color           = "#000000"
      GtkWidget::secondary-cursor-color = "#000000"
    }
    
    widget_class "*" style "custom"
    

    This style specifies the black color for the default layout.

    Third you need to create a symlink to the ~/.gtkrc-custom-us file: ln -sf /home/<username>/.gtkrc-custom-us /home/<username>/.gtkrc-custom.

    Note the symlink should be named .gtkrc-custom.

    Fourth you need to place an application directory somewhere. You could move it to the ~/my_scripts directory for example.

    Fifth you should change the lines 30, 31 and 32 of the ruby script replacing the default Russian layout to your own.
    30. when 'RU' # change to your layout
    31.   if File.readlink("#{home}/.gtkrc-custom") != "#{home}/.gtkrc-custom-ru" # change the .gtkrc-custom-ru file to .gtkrc-custom-<your_language> here
    32.     ln_sf("#{home}/.gtkrc-custom-ru", "#{home}/.gtkrc-custom") # and here
    

    And after all of that you can run the script <path_to_layout_indicator>/switch_layout_style.rb. Of course you should have the reload_gtk_settings.py, switch_layout_style.rb and show_the_current_layout files executable. You can use the chmod u+x <filename> command to change ther modes.

    To have an ability to autoload that script you can add it to the application list which GNOME loads on the start. To achieve it you should start the application launcher (usually Alt+F2) and then type gnome-session-properties there. The session window should appear and after that you can add the script to the autoloaded application list.

    Here's the list of the features that I would like to add to the application.

    - an ability to load the application at the start of the system but not GNOME's;
    - an ability to change another properties of the text cursor such as its width, blink rate etc.;
    - an ability to change the cursor's properties not only for GTK applications but also for Qt and XUL.;
    - an ability to change the cursor's color in the console;
    - an ability to change the color of the rectangular selection box.

    I'd like to hear what you think about how to realise them.

    I attach the files of the application to the post. The archive contains the application itself in the layout_indicator directory and the source code of xkblayout. Probably, you'll need to compile it by itself. If so don't forget to rename the output executable file to show_the_current_layout and add it to the layout_indicator dir.

    [file name=layout_indicator_source.tar.gz size=4086]http://www.linux.com/media/kunena/attachments/legacy/files/layout_indicator_source-fca906721321cd80791ca9b06754da7e.gz[/file]
  • jabirali
    jabirali Posts: 157
    Good job, this project is definitely going in the right direction!

    By the way, to make it easier for end users to configure, what do you think of the following approach:[ul][li]Rename ~/.gtkrc-custom-ru and ~/.gtkrc-custom-en to something like ~/.gtkrc-custom-main and ~/.gtkrc-custom-alt[/li][li]Make switch_layout_style.rb automatically run show_the_current_layout when it is started, and save the output to some variable (lets say kbd_default).[/li][li]Use ~/.gtkrc-custom-main whenever the current keyboard layout is set to $kbd_default, and use ~/.gtkrc-custom-alt when it is set to something else.[/li][/ul]If your keyboard daemon is automatically started when you login (see below), this approach would make the settings in ~/.gtkrc-custom-main be used whenever you use your default keymap (the one used first when you start X), and the settings in ~/.gtkrc-custom-alt would be used when you use your other keymaps. And the user wouldn't have to configure anything.

    As for your questions:

    1. An ability to load the application at the start of the system but not GNOME's;
    According to the freedesktop.org standards, autostart applications should be defined in the directory $XDG_CONFIG_DIRS/autostart/ (system-wide configuration) or $XDG_CONFIG_HOME/autostart/ (per-user configuration). If the variables are not set, $XDG_CONFIG_DIRS defaults to /etc/xdg/ and $XDG_CONFIG_HOME defaults to ~/.config/. To get your application automatically started, you should place a .desktop-file for it in one of these directories.

    Here's a simple .desktop file I created. I placed your program in /opt/layoutindicator/ and the following autostart file in /etc/xdg/autostart/layoutindicator.desktop, and it worked :)
    [Desktop Entry]
    Name=Keyboard Layout Indicator
    Comment=Changes settings based on current keyboard layout
    Exec=ruby /opt/layoutindicator/switch_layout_style.rb
    Terminal=false
    Type=Application
    


    2. An ability to change another properties of the text cursor such as its width, blink rate etc.;
    That should be easy by tweaking the custom ~/.gtkrc. Here are the relevant portions of the GTK+ Reference Manual:
    "gtk-cursor-blink" boolean
    Whether the cursor should blink.
    Default value: TRUE

    "gtk-cursor-blink-time" integer
    Length of the cursor blink cycle, in milleseconds.
    Allowed values: >= 100
    Default value: 1200
    I'm not sure how to change the cursor width, but that might be possible too.

    3. An ability to change the cursor's properties not only for GTK applications but also for Qt and XUL.
    This should definitely be possible, but I'm afraid I don't know how to do it. Let's hope either Google or a friendly Qt wizard knows how :-)

    4. An ability to change the cursor's color in the console
    I don't think this is possible. You might be able to reconfigure the cursor color of specific terminal emulators – by using gconf for gnome-terminal and the file ~/.Xresources for most other terminals – but you would (1) have to reconfigure the settings of every terminal emulator separately, and (2) I'm not sure you could reload the settings without restarting the terminal.

    5. An ability to change the color of the rectangular selection box.
    I know that this one is possible. Remember that all GTK2 themes do their magic by using a gtkrc file, and different themes use different colors for their selection boxes. For inspiration, I tried to look inside /usr/share/themes/Industrial/gtk-2.0/gtkrc, and experimented with putting the options that looked relevant in my ~/.gtkrc-custom files. Modifying one of the ~/.gtkrc-custom files to the following did the trick:
    style "custom" {
      GtkWidget::cursor-color           = "#FF0000"
      GtkWidget::secondary-cursor-color = "#FF0000"
      base[SELECTED]        = "#FF0000"
      text[SELECTED]        = "#000000"
    }
    
    widget_class "*" style "custom"
    

    Suggestions
    I also have a couple of other suggestions for your project. If you're planning a configuration utility of some kind, it should be able to:[ul][li]Enable/disable autostarting this daemon by modifying a .desktop file in ~/.config/autostart/. (Local settings always override the system defaults in /etc/xdg/autostart/.)[/li][li]Autogenerate ~/.gtkrc-custom-files if they don't exist[/li][li]Change the colors associated with the two keyboard layouts. If you plan to implement a graphical configuration utility, a color picker (similar to gcolor2) would be nice. There should also be a function to just swap the places of the two gtkrc-files.[/li][/ul]
    It might also be possible to use the Ruby bindings for GTK2 to force re-reading gtkrc-files. That would mean that you could drop the Python dependencies of your application, and reduce the footprint by not needing two different interpreters.

    [edit]
    To mods: Perhaps the thread should be moved from Getting Started with Linux to Software Development now :P
  • Goineasy9
    Goineasy9 Posts: 1,114
    Wow, guys, this is some great stuff.

Categories

Upcoming Training