Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: src/views/unix/SkOSWindow_Unix.cpp

Issue 17275003: use select() so we can wait for XEvents or our timer (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/views/SkOSWindow_Unix.h ('k') | src/views/unix/skia_unix.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 #include <X11/Xlib.h> 8 #include <X11/Xlib.h>
9 #include <X11/Xatom.h> 9 #include <X11/Xatom.h>
10 #include <X11/XKBlib.h> 10 #include <X11/XKBlib.h>
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 0, 0, // x, y 142 0, 0, // x, y
143 WIDTH, HEIGHT, 143 WIDTH, HEIGHT,
144 0, // border width 144 0, // border width
145 0, // border value 145 0, // border value
146 0); // background value 146 0); // background value
147 } 147 }
148 this->mapWindowAndWait(); 148 this->mapWindowAndWait();
149 fUnixWindow.fGc = XCreateGC(dsp, fUnixWindow.fWin, 0, NULL); 149 fUnixWindow.fGc = XCreateGC(dsp, fUnixWindow.fWin, 0, NULL);
150 } 150 }
151 151
152
153 void SkOSWindow::post_linuxevent() {
154 // Put an event in the X queue to fire an SkEvent.
155 if (NULL == fUnixWindow.fDisplay) {
156 return;
157 }
158 XClientMessageEvent event;
159 event.type = ClientMessage;
160 Atom myAtom(0);
161 event.message_type = myAtom;
162 event.format = 32;
163 event.data.l[0] = 0;
164 XSendEvent(fUnixWindow.fDisplay, fUnixWindow.fWin, false, 0,
165 (XEvent*) &event);
166 XFlush(fUnixWindow.fDisplay);
167 }
168
169 static unsigned getModi(const XEvent& evt) { 152 static unsigned getModi(const XEvent& evt) {
170 static const struct { 153 static const struct {
171 unsigned fXMask; 154 unsigned fXMask;
172 unsigned fSkMask; 155 unsigned fSkMask;
173 } gModi[] = { 156 } gModi[] = {
174 // X values found by experiment. Is there a better way? 157 // X values found by experiment. Is there a better way?
175 { 1, kShift_SkModifierKey }, 158 { 1, kShift_SkModifierKey },
176 { 4, kControl_SkModifierKey }, 159 { 4, kControl_SkModifierKey },
177 { 8, kOption_SkModifierKey }, 160 { 8, kOption_SkModifierKey },
178 }; 161 };
179 162
180 unsigned modi = 0; 163 unsigned modi = 0;
181 for (size_t i = 0; i < SK_ARRAY_COUNT(gModi); ++i) { 164 for (size_t i = 0; i < SK_ARRAY_COUNT(gModi); ++i) {
182 if (evt.xkey.state & gModi[i].fXMask) { 165 if (evt.xkey.state & gModi[i].fXMask) {
183 modi |= gModi[i].fSkMask; 166 modi |= gModi[i].fSkMask;
184 } 167 }
185 } 168 }
186 return modi; 169 return modi;
187 } 170 }
188 171
172 static SkMSec gTimerDelay;
173
174 static void MyXNextEventWithDelay(Display* dsp, XEvent* evt) {
175 SkMSec ms = gTimerDelay;
176 if (ms > 0) {
177 int x11_fd = ConnectionNumber(dsp);
178 fd_set input_fds;
179 FD_ZERO(&input_fds);
180 FD_SET(x11_fd, &input_fds);
181
182 timeval tv;
183 tv.tv_sec = ms / 1000; // seconds
184 tv.tv_usec = (ms % 1000) * 1000; // microseconds
185
186 (void)select(x11_fd + 1, &input_fds, NULL, NULL, &tv);
187 }
188
189 if (XPending(dsp)) {
190 XNextEvent(dsp, evt);
191 }
192 }
193
194 SkOSWindow::NextXEventResult SkOSWindow::nextXEvent() {
195 XEvent evt;
196 Display* dsp = fUnixWindow.fDisplay;
197
198 MyXNextEventWithDelay(fUnixWindow.fDisplay, &evt);
199
200 switch (evt.type) {
201 case Expose:
202 if (0 == evt.xexpose.count) {
203 return kPaintRequest_NextXEventResult;
204 }
205 break;
206 case ConfigureNotify:
207 this->resize(evt.xconfigure.width, evt.xconfigure.height);
208 break;
209 case ButtonPress:
210 if (evt.xbutton.button == Button1)
211 this->handleClick(evt.xbutton.x, evt.xbutton.y,
212 SkView::Click::kDown_State, NULL, getModi(evt));
213 break;
214 case ButtonRelease:
215 if (evt.xbutton.button == Button1)
216 this->handleClick(evt.xbutton.x, evt.xbutton.y,
217 SkView::Click::kUp_State, NULL, getModi(evt));
218 break;
219 case MotionNotify:
220 this->handleClick(evt.xmotion.x, evt.xmotion.y,
221 SkView::Click::kMoved_State, NULL, getModi(evt));
222 break;
223 case KeyPress: {
224 int shiftLevel = (evt.xkey.keycode & ShiftMask) ? 1 : 0;
225 KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode,
226 0, shiftLevel);
227 if (keysym == XK_Escape) {
228 return kQuitRequest_NextXEventResult;
229 }
230 this->handleKey(XKeyToSkKey(keysym));
231 long uni = keysym2ucs(keysym);
232 if (uni != -1) {
233 this->handleChar((SkUnichar) uni);
234 }
235 break;
236 }
237 case KeyRelease:
238 this->handleKeyUp(XKeyToSkKey(XkbKeycodeToKeysym(dsp, evt.xkey.keyco de, 0, 0)));
239 break;
240 default:
241 // Do nothing for other events
242 break;
243 }
244 return kContinue_NextXEventResult;
245 }
246
189 void SkOSWindow::loop() { 247 void SkOSWindow::loop() {
190 Display* dsp = fUnixWindow.fDisplay; 248 Display* dsp = fUnixWindow.fDisplay;
191 if (NULL == dsp) { 249 if (NULL == dsp) {
192 return; 250 return;
193 } 251 }
194 XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK); 252 XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK);
195 253
196 bool loop = true; 254 bool needPaint = false;
197 XEvent evt; 255
198 while (loop) { 256 for (;;) {
199 XNextEvent(dsp, &evt); 257 if (this->isDirty()) {
200 switch (evt.type) { 258 this->update(NULL);
201 case Expose: 259 needPaint = true;
202 if (evt.xexpose.count == 0) 260 }
203 this->inval(NULL); 261 if (needPaint) {
204 break; 262 this->doPaint();
205 case ConfigureNotify: 263 needPaint = false;
206 this->resize(evt.xconfigure.width, evt.xconfigure.height); 264 }
207 break; 265 if (gTimerDelay) {
208 case ButtonPress: 266 SkEvent::ServiceQueueTimer();
209 if (evt.xbutton.button == Button1) 267 }
210 this->handleClick(evt.xbutton.x, evt.xbutton.y, 268 bool moreToDo = SkEvent::ProcessEvent() || needPaint || this->isDirty();
211 SkView::Click::kDown_State, NULL, getModi(evt)); 269 if (XPending(dsp) || !moreToDo) {
212 break; 270 switch (this->nextXEvent()) {
213 case ButtonRelease: 271 case kContinue_NextXEventResult:
214 if (evt.xbutton.button == Button1)
215 this->handleClick(evt.xbutton.x, evt.xbutton.y,
216 SkView::Click::kUp_State, NULL, getModi(evt));
217 break;
218 case MotionNotify:
219 this->handleClick(evt.xmotion.x, evt.xmotion.y,
220 SkView::Click::kMoved_State, NULL, getModi(evt));
221 break;
222 case KeyPress: {
223 KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0);
224 //SkDebugf("pressed key %i!\n\tKeySym:%i\n", evt.xkey.keycode, X KeycodeToKeysym(dsp, evt.xkey.keycode, 0));
225 if (keysym == XK_Escape) {
226 loop = false;
227 break; 272 break;
228 } 273 case kPaintRequest_NextXEventResult:
229 this->handleKey(XKeyToSkKey(keysym)); 274 needPaint = true;
230 long uni = keysym2ucs(keysym); 275 break;
231 if (uni != -1) { 276 case kQuitRequest_NextXEventResult:
232 this->handleChar((SkUnichar) uni); 277 return;
233 }
234 break;
235 } 278 }
236 case KeyRelease:
237 //SkDebugf("released key %i\n", evt.xkey.keycode);
238 this->handleKeyUp(XKeyToSkKey(XkbKeycodeToKeysym(dsp, evt.xkey.k eycode, 0, 0)));
239 break;
240 case ClientMessage:
241 if (SkEvent::ProcessEvent()) {
242 this->post_linuxevent();
243 }
244 break;
245 default:
246 // Do nothing for other events
247 break;
248 } 279 }
249 } 280 }
250 } 281 }
251 282
252 void SkOSWindow::mapWindowAndWait() { 283 void SkOSWindow::mapWindowAndWait() {
253 SkASSERT(NULL != fUnixWindow.fDisplay); 284 SkASSERT(NULL != fUnixWindow.fDisplay);
254 Display* dsp = fUnixWindow.fDisplay; 285 Display* dsp = fUnixWindow.fDisplay;
255 Window win = fUnixWindow.fWin; 286 Window win = fUnixWindow.fWin;
256 XMapWindow(dsp, win); 287 XMapWindow(dsp, win);
257 288
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 return; 345 return;
315 } 346 }
316 XTextProperty textProp; 347 XTextProperty textProp;
317 textProp.value = (unsigned char*)title; 348 textProp.value = (unsigned char*)title;
318 textProp.format = 8; 349 textProp.format = 8;
319 textProp.nitems = strlen((char*)textProp.value); 350 textProp.nitems = strlen((char*)textProp.value);
320 textProp.encoding = XA_STRING; 351 textProp.encoding = XA_STRING;
321 XSetWMName(fUnixWindow.fDisplay, fUnixWindow.fWin, &textProp); 352 XSetWMName(fUnixWindow.fDisplay, fUnixWindow.fWin, &textProp);
322 } 353 }
323 354
324 void SkOSWindow::onHandleInval(const SkIRect&) {
325 (new SkEvent("inval-imageview", this->getSinkID()))->post();
326 }
327
328 bool SkOSWindow::onEvent(const SkEvent& evt) {
329 if (evt.isType("inval-imageview")) {
330 update(NULL);
331 if (NULL == fUnixWindow.fGLContext)
332 this->doPaint();
333 return true;
334 }
335 return INHERITED::onEvent(evt);
336 }
337
338 static bool convertBitmapToXImage(XImage& image, const SkBitmap& bitmap) { 355 static bool convertBitmapToXImage(XImage& image, const SkBitmap& bitmap) {
339 sk_bzero(&image, sizeof(image)); 356 sk_bzero(&image, sizeof(image));
340 357
341 int bitsPerPixel = bitmap.bytesPerPixel() * 8; 358 int bitsPerPixel = bitmap.bytesPerPixel() * 8;
342 image.width = bitmap.width(); 359 image.width = bitmap.width();
343 image.height = bitmap.height(); 360 image.height = bitmap.height();
344 image.format = ZPixmap; 361 image.format = ZPixmap;
345 image.data = (char*) bitmap.getPixels(); 362 image.data = (char*) bitmap.getPixels();
346 image.byte_order = LSBFirst; 363 image.byte_order = LSBFirst;
347 image.bitmap_unit = bitsPerPixel; 364 image.bitmap_unit = bitsPerPixel;
348 image.bitmap_bit_order = LSBFirst; 365 image.bitmap_bit_order = LSBFirst;
349 image.bitmap_pad = bitsPerPixel; 366 image.bitmap_pad = bitsPerPixel;
350 image.depth = 24; 367 image.depth = 24;
351 image.bytes_per_line = bitmap.rowBytes() - bitmap.width() * bitmap.bytesPerP ixel(); 368 image.bytes_per_line = bitmap.rowBytes() - bitmap.width() * 4;
352 image.bits_per_pixel = bitsPerPixel; 369 image.bits_per_pixel = bitsPerPixel;
353 return XInitImage(&image); 370 return XInitImage(&image);
354 } 371 }
355 372
356 void SkOSWindow::doPaint() { 373 void SkOSWindow::doPaint() {
357 if (NULL == fUnixWindow.fDisplay) { 374 if (NULL == fUnixWindow.fDisplay) {
358 return; 375 return;
359 } 376 }
360 // Draw the bitmap to the screen. 377 // Draw the bitmap to the screen.
361 const SkBitmap& bitmap = getBitmap(); 378 const SkBitmap& bitmap = getBitmap();
362 int width = bitmap.width(); 379 int width = bitmap.width();
363 int height = bitmap.height(); 380 int height = bitmap.height();
364 381
365 XImage image; 382 XImage image;
366 if (!convertBitmapToXImage(image, bitmap)) { 383 if (!convertBitmapToXImage(image, bitmap)) {
367 return; 384 return;
368 } 385 }
369 386
370 XPutImage(fUnixWindow.fDisplay, 387 XPutImage(fUnixWindow.fDisplay,
371 fUnixWindow.fWin, 388 fUnixWindow.fWin,
372 fUnixWindow.fGc, 389 fUnixWindow.fGc,
373 &image, 390 &image,
374 0, 0, // src x,y 391 0, 0, // src x,y
375 0, 0, // dst x,y 392 0, 0, // dst x,y
376 width, height); 393 width, height);
377 } 394 }
378 395
379 bool SkOSWindow::onHandleChar(SkUnichar) { 396 ///////////////////////////////////////////////////////////////////////////////
380 return false; 397
398 void SkEvent::SignalNonEmptyQueue() {
399 // nothing to do, since we spin on our event-queue, polling for XPending
381 } 400 }
382 401
383 bool SkOSWindow::onHandleKey(SkKey) { 402 void SkEvent::SignalQueueTimer(SkMSec delay) {
384 return false; 403 // just need to record the delay time. We handle waking up for it in
404 // MyXNextEventWithDelay()
405 gTimerDelay = delay;
385 } 406 }
386 407
387 bool SkOSWindow::onHandleKeyUp(SkKey) {
388 return false;
389 }
OLDNEW
« no previous file with comments | « include/views/SkOSWindow_Unix.h ('k') | src/views/unix/skia_unix.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698