From acb3d88cf84adf367c173a7a33cd3b0c379291dc Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Mon, 17 Jun 2013 13:42:43 +0000 Subject: use select() so we can wait for XEvents or our timer poll for xevents using XPending BUG= Review URL: https://codereview.chromium.org/17275003 git-svn-id: http://skia.googlecode.com/svn/trunk@9633 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/views/unix/SkOSWindow_Unix.cpp | 196 ++++++++++++++++++++----------------- src/views/unix/skia_unix.cpp | 23 ----- 2 files changed, 107 insertions(+), 112 deletions(-) (limited to 'src/views') diff --git a/src/views/unix/SkOSWindow_Unix.cpp b/src/views/unix/SkOSWindow_Unix.cpp index a20644556d..591493e57e 100644 --- a/src/views/unix/SkOSWindow_Unix.cpp +++ b/src/views/unix/SkOSWindow_Unix.cpp @@ -149,23 +149,6 @@ void SkOSWindow::initWindow(int requestedMSAASampleCount, AttachmentInfo* info) fUnixWindow.fGc = XCreateGC(dsp, fUnixWindow.fWin, 0, NULL); } - -void SkOSWindow::post_linuxevent() { - // Put an event in the X queue to fire an SkEvent. - if (NULL == fUnixWindow.fDisplay) { - return; - } - XClientMessageEvent event; - event.type = ClientMessage; - Atom myAtom(0); - event.message_type = myAtom; - event.format = 32; - event.data.l[0] = 0; - XSendEvent(fUnixWindow.fDisplay, fUnixWindow.fWin, false, 0, - (XEvent*) &event); - XFlush(fUnixWindow.fDisplay); -} - static unsigned getModi(const XEvent& evt) { static const struct { unsigned fXMask; @@ -186,6 +169,81 @@ static unsigned getModi(const XEvent& evt) { return modi; } +static SkMSec gTimerDelay; + +static void MyXNextEventWithDelay(Display* dsp, XEvent* evt) { + SkMSec ms = gTimerDelay; + if (ms > 0) { + int x11_fd = ConnectionNumber(dsp); + fd_set input_fds; + FD_ZERO(&input_fds); + FD_SET(x11_fd, &input_fds); + + timeval tv; + tv.tv_sec = ms / 1000; // seconds + tv.tv_usec = (ms % 1000) * 1000; // microseconds + + (void)select(x11_fd + 1, &input_fds, NULL, NULL, &tv); + } + + if (XPending(dsp)) { + XNextEvent(dsp, evt); + } +} + +SkOSWindow::NextXEventResult SkOSWindow::nextXEvent() { + XEvent evt; + Display* dsp = fUnixWindow.fDisplay; + + MyXNextEventWithDelay(fUnixWindow.fDisplay, &evt); + + switch (evt.type) { + case Expose: + if (0 == evt.xexpose.count) { + return kPaintRequest_NextXEventResult; + } + break; + case ConfigureNotify: + this->resize(evt.xconfigure.width, evt.xconfigure.height); + break; + case ButtonPress: + if (evt.xbutton.button == Button1) + this->handleClick(evt.xbutton.x, evt.xbutton.y, + SkView::Click::kDown_State, NULL, getModi(evt)); + break; + case ButtonRelease: + if (evt.xbutton.button == Button1) + this->handleClick(evt.xbutton.x, evt.xbutton.y, + SkView::Click::kUp_State, NULL, getModi(evt)); + break; + case MotionNotify: + this->handleClick(evt.xmotion.x, evt.xmotion.y, + SkView::Click::kMoved_State, NULL, getModi(evt)); + break; + case KeyPress: { + int shiftLevel = (evt.xkey.keycode & ShiftMask) ? 1 : 0; + KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode, + 0, shiftLevel); + if (keysym == XK_Escape) { + return kQuitRequest_NextXEventResult; + } + this->handleKey(XKeyToSkKey(keysym)); + long uni = keysym2ucs(keysym); + if (uni != -1) { + this->handleChar((SkUnichar) uni); + } + break; + } + case KeyRelease: + this->handleKeyUp(XKeyToSkKey(XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0))); + break; + default: + // Do nothing for other events + break; + } + return kContinue_NextXEventResult; +} + void SkOSWindow::loop() { Display* dsp = fUnixWindow.fDisplay; if (NULL == dsp) { @@ -193,58 +251,31 @@ void SkOSWindow::loop() { } XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK); - bool loop = true; - XEvent evt; - while (loop) { - XNextEvent(dsp, &evt); - switch (evt.type) { - case Expose: - if (evt.xexpose.count == 0) - this->inval(NULL); - break; - case ConfigureNotify: - this->resize(evt.xconfigure.width, evt.xconfigure.height); - break; - case ButtonPress: - if (evt.xbutton.button == Button1) - this->handleClick(evt.xbutton.x, evt.xbutton.y, - SkView::Click::kDown_State, NULL, getModi(evt)); - break; - case ButtonRelease: - if (evt.xbutton.button == Button1) - this->handleClick(evt.xbutton.x, evt.xbutton.y, - SkView::Click::kUp_State, NULL, getModi(evt)); - break; - case MotionNotify: - this->handleClick(evt.xmotion.x, evt.xmotion.y, - SkView::Click::kMoved_State, NULL, getModi(evt)); - break; - case KeyPress: { - KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0); - //SkDebugf("pressed key %i!\n\tKeySym:%i\n", evt.xkey.keycode, XKeycodeToKeysym(dsp, evt.xkey.keycode, 0)); - if (keysym == XK_Escape) { - loop = false; + bool needPaint = false; + + for (;;) { + if (this->isDirty()) { + this->update(NULL); + needPaint = true; + } + if (needPaint) { + this->doPaint(); + needPaint = false; + } + if (gTimerDelay) { + SkEvent::ServiceQueueTimer(); + } + bool moreToDo = SkEvent::ProcessEvent() || needPaint || this->isDirty(); + if (XPending(dsp) || !moreToDo) { + switch (this->nextXEvent()) { + case kContinue_NextXEventResult: break; - } - this->handleKey(XKeyToSkKey(keysym)); - long uni = keysym2ucs(keysym); - if (uni != -1) { - this->handleChar((SkUnichar) uni); - } - break; + case kPaintRequest_NextXEventResult: + needPaint = true; + break; + case kQuitRequest_NextXEventResult: + return; } - case KeyRelease: - //SkDebugf("released key %i\n", evt.xkey.keycode); - this->handleKeyUp(XKeyToSkKey(XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0))); - break; - case ClientMessage: - if (SkEvent::ProcessEvent()) { - this->post_linuxevent(); - } - break; - default: - // Do nothing for other events - break; } } } @@ -321,20 +352,6 @@ void SkOSWindow::onSetTitle(const char title[]) { XSetWMName(fUnixWindow.fDisplay, fUnixWindow.fWin, &textProp); } -void SkOSWindow::onHandleInval(const SkIRect&) { - (new SkEvent("inval-imageview", this->getSinkID()))->post(); -} - -bool SkOSWindow::onEvent(const SkEvent& evt) { - if (evt.isType("inval-imageview")) { - update(NULL); - if (NULL == fUnixWindow.fGLContext) - this->doPaint(); - return true; - } - return INHERITED::onEvent(evt); -} - static bool convertBitmapToXImage(XImage& image, const SkBitmap& bitmap) { sk_bzero(&image, sizeof(image)); @@ -348,7 +365,7 @@ static bool convertBitmapToXImage(XImage& image, const SkBitmap& bitmap) { image.bitmap_bit_order = LSBFirst; image.bitmap_pad = bitsPerPixel; image.depth = 24; - image.bytes_per_line = bitmap.rowBytes() - bitmap.width() * bitmap.bytesPerPixel(); + image.bytes_per_line = bitmap.rowBytes() - bitmap.width() * 4; image.bits_per_pixel = bitsPerPixel; return XInitImage(&image); } @@ -376,14 +393,15 @@ void SkOSWindow::doPaint() { width, height); } -bool SkOSWindow::onHandleChar(SkUnichar) { - return false; -} +/////////////////////////////////////////////////////////////////////////////// -bool SkOSWindow::onHandleKey(SkKey) { - return false; +void SkEvent::SignalNonEmptyQueue() { + // nothing to do, since we spin on our event-queue, polling for XPending } -bool SkOSWindow::onHandleKeyUp(SkKey) { - return false; +void SkEvent::SignalQueueTimer(SkMSec delay) { + // just need to record the delay time. We handle waking up for it in + // MyXNextEventWithDelay() + gTimerDelay = delay; } + diff --git a/src/views/unix/skia_unix.cpp b/src/views/unix/skia_unix.cpp index 108e9ac206..d77a8161fb 100644 --- a/src/views/unix/skia_unix.cpp +++ b/src/views/unix/skia_unix.cpp @@ -18,14 +18,7 @@ SkOSWindow* gWindow; -static void catch_alarm(int sig) -{ - SkEvent::ServiceQueueTimer(); -} - int main(int argc, char** argv){ - signal(SIGALRM, catch_alarm); - gWindow = create_sk_window(NULL, argc, argv); // drain any events that occurred before gWindow was assigned. @@ -43,20 +36,4 @@ int main(int argc, char** argv){ // SkEvent handlers -void SkEvent::SignalNonEmptyQueue() -{ - if (gWindow) { - gWindow->post_linuxevent(); - } -} - -void SkEvent::SignalQueueTimer(SkMSec delay) -{ - itimerval newTimer; - newTimer.it_interval.tv_sec = 0; - newTimer.it_interval.tv_usec = 0; - newTimer.it_value.tv_sec = 0; - newTimer.it_value.tv_usec = delay * 1000; - setitimer(ITIMER_REAL, &newTimer, NULL); -} -- cgit v1.2.3