11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include <X11/Xlib.h>
935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include <X11/Xatom.h>
1035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include <X11/keysym.h>
1135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include <GL/glx.h>
1235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include <GL/gl.h>
1335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include <GL/glu.h>
1435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkWindow.h"
1635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkBitmap.h"
1835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkCanvas.h"
1935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkColor.h"
2035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkEvent.h"
2135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkKey.h"
2235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkWindow.h"
2335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "XkeysToSkKeys.h"
2435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerextern "C" {
2535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    #include "keysym2ucs.h"
2635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
2735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
280199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenbergerconst int WIDTH = 500;
290199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenbergerconst int HEIGHT = 500;
3035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
3135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// Determine which events to listen for.
3235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerconst long EVENT_MASK = StructureNotifyMask|ButtonPressMask|ButtonReleaseMask
3335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        |ExposureMask|PointerMotionMask|KeyPressMask|KeyReleaseMask;
3435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
351cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkOSWindow::SkOSWindow(void* unused) : INHERITED(), fGLAttached(false), fVi(0)
3635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
3735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    fUnixWindow.fDisplay = XOpenDisplay(NULL);
3835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    Display* dsp = fUnixWindow.fDisplay;
3935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (dsp) {
4035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // Attempt to create a window that supports GL
4135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER,
4235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                GLX_STENCIL_SIZE, 8, None };
430199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger        fVi = glXChooseVisual(dsp, DefaultScreen(dsp), att);
4435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (fVi) {
450199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger            Colormap colorMap = XCreateColormap(dsp, RootWindow(dsp, fVi->screen),
460199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger                fVi->visual, AllocNone);
4735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            XSetWindowAttributes swa;
480199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger            swa.colormap = colorMap;
4935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            swa.event_mask = EVENT_MASK;
500199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger            fUnixWindow.fWin = XCreateWindow(dsp, RootWindow(dsp, fVi->screen),
5135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    0, 0, WIDTH, HEIGHT, 0, fVi->depth,
520199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger                    InputOutput, fVi->visual, CWEventMask | CWColormap, &swa);
5335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
5435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        } else {
5535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            // Create a simple window instead.  We will not be able to
5635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            // show GL
5735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            fUnixWindow.fWin = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp),
5835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    0, 0, WIDTH, HEIGHT, 0, 0, 0);
5935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
6035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        mapWindowAndWait();
6135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fUnixWindow.fGc = XCreateGC(dsp, fUnixWindow.fWin, 0, NULL);
6235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
6335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    this->resize(WIDTH, HEIGHT);
6435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    fUnixWindow.fGLCreated = false;
6535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
6635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
6735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek SollenbergerSkOSWindow::~SkOSWindow()
6835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
6935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (fUnixWindow.fDisplay) {
7035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (fGLAttached)
7135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            glXMakeCurrent(fUnixWindow.fDisplay, None, NULL);
7235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        XFreeGC(fUnixWindow.fDisplay, fUnixWindow.fGc);
7335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (fUnixWindow.fGLCreated)
7435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            glXDestroyContext(fUnixWindow.fDisplay, fUnixWindow.fGLContext);
7535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        XDestroyWindow(fUnixWindow.fDisplay, fUnixWindow.fWin);
7635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        XCloseDisplay(fUnixWindow.fDisplay);
7735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fUnixWindow.fDisplay = 0;
7835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
7935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
8035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::post_linuxevent()
8235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
8335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // Put an event in the X queue to fire an SkEvent.
8435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!fUnixWindow.fDisplay) return;
8535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    long event_mask = NoEventMask;
8635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XClientMessageEvent event;
8735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    event.type = ClientMessage;
880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    Atom myAtom(0);
8935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    event.message_type = myAtom;
9035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    event.format = 32;
9135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    event.data.l[0] = 0;
9235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XSendEvent(fUnixWindow.fDisplay, fUnixWindow.fWin, false, 0,
9335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger               (XEvent*) &event);
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    XFlush(fUnixWindow.fDisplay);
9535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
9635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::loop()
9835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
9935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    Display* dsp = fUnixWindow.fDisplay;
10035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK);
10135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
10235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    bool loop = true;
10335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XEvent evt;
10435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    while (loop) {
10535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        XNextEvent(dsp, &evt);
10635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        switch (evt.type) {
10735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case Expose:
10835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (evt.xexpose.count == 0)
10935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    this->inval(NULL);
11035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
11135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case ConfigureNotify:
11235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                this->resize(evt.xconfigure.width, evt.xconfigure.height);
11335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
11435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case ButtonPress:
11535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (evt.xbutton.button == Button1)
11635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kDown_State);
11735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
11835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case ButtonRelease:
11935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (evt.xbutton.button == Button1)
12035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kUp_State);
12135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
12235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case MotionNotify:
12335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                this->handleClick(evt.xmotion.x, evt.xmotion.y, SkView::Click::kMoved_State);
12435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
12535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case KeyPress:
12635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            {
12735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                KeySym keysym = XKeycodeToKeysym(dsp, evt.xkey.keycode, 0);
12835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                //SkDebugf("pressed key %i!\n\tKeySym:%i\n", evt.xkey.keycode, XKeycodeToKeysym(dsp, evt.xkey.keycode, 0));
12935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (keysym == XK_Escape) {
13035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    loop = false;
13135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    break;
13235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                }
13335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                this->handleKey(XKeyToSkKey(keysym));
13435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                long uni = keysym2ucs(keysym);
13535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (uni != -1) {
13635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    this->handleChar((SkUnichar) uni);
13735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                }
13835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
13935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            }
14035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case KeyRelease:
14135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                //SkDebugf("released key %i\n", evt.xkey.keycode);
14235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                this->handleKeyUp(XKeyToSkKey(XKeycodeToKeysym(dsp, evt.xkey.keycode, 0)));
14335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
14435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            case ClientMessage:
14535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (SkEvent::ProcessEvent()) {
14635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    this->post_linuxevent();
14735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                }
14835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
14935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            default:
15035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                // Do nothing for other events
15135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                break;
15235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
15335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
15435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
15535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
15635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::mapWindowAndWait()
15735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
15835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    Display* dsp = fUnixWindow.fDisplay;
15935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    Window win = fUnixWindow.fWin;
16035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XMapWindow(dsp, win);
16135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
16235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    long eventMask = StructureNotifyMask;
16335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XSelectInput(dsp, win, eventMask);
16435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
16535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // Wait until screen is ready.
16635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XEvent evt;
16735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    do {
16835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        XNextEvent(dsp, &evt);
16935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    } while(evt.type != MapNotify);
17035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
17135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
17235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
17335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkOSWindow::attachGL()
17435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
17535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (fGLAttached) return true;
17635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    Display* dsp = fUnixWindow.fDisplay;
17735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!dsp || !fVi) return false;
17835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
17935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!fUnixWindow.fGLCreated) {
18035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fUnixWindow.fGLContext = glXCreateContext(dsp, fVi, NULL, GL_TRUE);
18135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fUnixWindow.fGLCreated = true;
18235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glXMakeCurrent(dsp, fUnixWindow.fWin, fUnixWindow.fGLContext);
18335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glViewport(0, 0, SkScalarRound(this->width()), SkScalarRound(this->height()));
18435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glClearColor(0, 0, 0, 0);
18535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glClearStencil(0);
18635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glStencilMask(0xffffffff);
18735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glDisable(GL_SCISSOR_TEST);
18835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
18935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
19035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    else
19135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glXMakeCurrent(dsp, fUnixWindow.fWin, fUnixWindow.fGLContext);
19235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    fGLAttached = true;
19335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
19435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return true;
19535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
19635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
19735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::detachGL()
19835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
19935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!fUnixWindow.fDisplay || !fGLAttached) return;
20035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    fGLAttached = false;
20135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // Returns back to normal drawing.
20235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    glXMakeCurrent(fUnixWindow.fDisplay, None, NULL);
20335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // Ensure that we redraw when switching back to raster.
20435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    this->inval(NULL);
20535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
20635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
20735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::presentGL()
20835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
20935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (fUnixWindow.fDisplay && fGLAttached) {
21035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        glXSwapBuffers(fUnixWindow.fDisplay, fUnixWindow.fWin);
21135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
21235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
21335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
21435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::onSetTitle(const char title[])
21535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
21635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!fUnixWindow.fDisplay) return;
21735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XTextProperty textProp;
21835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    textProp.value = (unsigned char*)title;
21935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    textProp.format = 8;
22035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    textProp.nitems = strlen((char*)textProp.value);
22135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    textProp.encoding = XA_STRING;
22235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XSetWMName(fUnixWindow.fDisplay, fUnixWindow.fWin, &textProp);
22335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
22435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkOSWindow::onHandleInval(const SkIRect&) {
2261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    (new SkEvent("inval-imageview", this->getSinkID()))->post();
22735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
22835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
22935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkOSWindow::onEvent(const SkEvent& evt)
23035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
23135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (evt.isType("inval-imageview")) {
23235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        update(NULL);
23335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (!fGLAttached)
23435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            doPaint();
23535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return true;
23635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
23735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return INHERITED::onEvent(evt);
23835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
23935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
24035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic bool convertBitmapToXImage(XImage& image, const SkBitmap& bitmap)
24135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
24235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    sk_bzero(&image, sizeof(image));
24335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
24435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int bitsPerPixel = bitmap.bytesPerPixel() * 8;
24535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.width = bitmap.width();
24635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.height = bitmap.height();
24735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.format = ZPixmap;
24835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.data = (char*) bitmap.getPixels();
24935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.byte_order = LSBFirst;
25035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.bitmap_unit = bitsPerPixel;
25135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.bitmap_bit_order = LSBFirst;
25235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.bitmap_pad = bitsPerPixel;
25335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.depth = 24;
25435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.bytes_per_line = bitmap.rowBytes() - bitmap.width() * bitmap.bytesPerPixel();
25535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    image.bits_per_pixel = bitsPerPixel;
25635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return XInitImage(&image);
25735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
25835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
25935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkOSWindow::doPaint() {
26035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!fUnixWindow.fDisplay) return;
26135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // Draw the bitmap to the screen.
26235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    const SkBitmap& bitmap = getBitmap();
26335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int width = bitmap.width();
26435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int height = bitmap.height();
26535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
26635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XImage image;
26735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (!convertBitmapToXImage(image, bitmap)) return;
26835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
26935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    XPutImage(fUnixWindow.fDisplay, fUnixWindow.fWin, fUnixWindow.fGc, &image, 0, 0, 0, 0, width, height);
27035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
27135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
27235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkOSWindow::onHandleChar(SkUnichar)
27335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
27435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return false;
27535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
27635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
27735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkOSWindow::onHandleKey(SkKey key)
27835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
27935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return false;
28035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
28135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
28235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkOSWindow::onHandleKeyUp(SkKey key)
28335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
28435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return false;
28535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
286