PEG cursors--humppake: Changing mouse cursor

Author: Asko Soukka
Date-Created:2003-05-09
Last-Modified:2003-05-16
Revision: 1.12
Status: Implemented
Scope:Trivial
Type:Feature, Interface, Implementation

This peg describes, how changing of the mouse cursor to any of the default system cursors could be easily implemented on LibVob.

Issues

Changes

Interfaces

Into org.nongnu.libvob.GraphicsAPI.Window:

/** Set the mouse cursor for the window.
 * Available cursor types. These are similar to ones
 * in java.awt.Cursor, tough the "_CURSOR" suffix
 * is dropped.
 *
 * "CROSSHAIR"  The crosshair cursor type.
 * "DEFAULT" The default cursor type (gets set if no cursor is defined).
 * "E_RESIZE" The east-resize cursor type.
 * "HAND" The hand cursor type.
 * "MOVE" The move cursor type.
 * "N_RESIZE" The north-resize cursor type.
 * "NE_RESIZE" The north-east-resize cursor type.
 * "NW_RESIZE" The north-west-resize cursor type.
 * "S_RESIZE" The south-resize cursor type.
 * "SE_RESIZE" The south-east-resize cursor type.
 * "SW_RESIZE" The south-west-resize cursor type.
 * "TEXT" The text cursor type.
 * "W_RESIZE" The west-resize cursor type.
 * "WAIT" The wait cursor type.
 */
public void setCursor(String name);

Into org.nongnu.libvob.impl.awt.AWTScreen:

/** Set the mouse cursor for the window.
 */ 
public void setCursor(Cursor cursor) {
    canvas.setCursor(cursor);
}

Implementation

Description

Java AWT client uses java.awt.Cursor, which can be passed to any java.awt.Component - like ScreenCanvas in AWTScreen. GL client needs a platform specific implementation. Currently we are supporting X implementation. In X Windows, mouse cursor could be changed via Xlib.

In GL implementation, the cursor name string is passed on in org.nongnu.libvob.impl.gl.GLScreen and the low level implementation like using Xlib is determined later on. Most probably in /src/os/Os-GLX.

In AWT the cursor, name string is converted to corresponding java.awt.Cursor, which is passed to proper AWT component.

Java

Into org.nongnu.libvob.impl.awt.AWTScreen:

public void setCursor(String name) {
    try {
        Cursor cursor = new Cursor(Cursor.class.getField(name.toUpperCase()+"_CURSOR").getInt(null));
        canvas.setCursor(cursor);
    } catch (Exception e) {
        throw new IllegalArgumentException("Unknown cursor: "+name);
    }
}

Into org.nongnu.libvob.gl.GL.Window:

/** Set the mouse cursor of the window.
 */
public void setCursor(String name) { impl_Window_setCursor(getId(), name); }

Into org.nongnu.libvob.gl.GL:

static private native void impl_Window_setCursor(int id, String name);

Into org.nongnu.libvob.impl.GL.GLScreen:

public void setCursor(String name) {
  name = name.toUpperCase();
  if (name.equals("CROSSHAIR") ||
      name.equals("DEFAULT") ||
      name.equals("E_RESIZE") ||
      name.equals("HAND") ||
      name.equals("MOVE") ||
      name.equals("N_RESIZE") ||
      name.equals("NE_RESIZE") ||
      name.equals("NW_RESIZE") ||
      name.equals("S_RESIZE") ||
      name.equals("SE_RESIZE") ||
      name.equals("SW_RESIZE") ||
      name.equals("TEXT") ||
      name.equals("W_RESIZE") ||
      name.equals("WAIT"))
        window.setCursor(name);
  else throw new IllegalArgumentException("Unknown cursor: "+name);
}

C

Into include/vob/os/Os.cxx Vob.Os.Window:

virtual void setCursor(const std::string name) = 0;

Into src/jni/Main.cxx:

jf(void, impl_1Window_1setCursor)
(JNIEnv *env, jclass, jint id, jstring name) {
      Os::Window *w = (Os::Window *)windows.get(id);
      DBG(dbg) << "Set window "<<id<<" Cursor name "<<name<<" at "<<(int)w<<"\n";
      std::string name_str = jstr2stdstr(env, name);
      w->setCursor(name_str);
}

Into src/os/Os-GLX.cxx:

// For setCursor()
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
//

Into src/os/Os-GLX.cxx Vob.Os.LXWindow:

virtual void setCursor(const std::string name) {
    Cursor cursor = 0;
    if (name == "CROSSHAIR")
      cursor = XCreateFontCursor(ws->dpy, XC_crosshair);
    else if (name == "DEFAULT")
      cursor = XCreateFontCursor(ws->dpy, XC_left_ptr);
    else if (name == "E_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_right_side);
    else if (name == "HAND")
      cursor = XCreateFontCursor(ws->dpy, XC_hand2);
    else if (name == "MOVE")
      cursor = XCreateFontCursor(ws->dpy, XC_fleur);
    else if (name == "N_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_top_side);
    else if (name == "NE_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_top_right_corner);
    else if (name == "NW_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_top_left_corner);
    else if (name == "S_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_bottom_side);
    else if (name == "SE_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_bottom_right_corner);
    else if (name == "SW_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_bottom_left_corner);
    else if (name == "TEXT")
      cursor = XCreateFontCursor(ws->dpy, XC_xterm);
    else if (name == "W_RESIZE")
      cursor = XCreateFontCursor(ws->dpy, XC_left_side);
    else if (name == "WAIT")
      cursor = XCreateFontCursor(ws->dpy, XC_watch);
    if (cursor != 0) XDefineCursor(ws->dpy, xw, cursor);
}