~ubuntu-branches/ubuntu/lucid/gnustep-back/lucid

« back to all changes in this revision

Viewing changes to Source/x11/XWindowBuffer.m

  • Committer: Bazaar Package Importer
  • Author(s): Hubert Chathi
  • Date: 2009-04-12 15:54:30 UTC
  • mfrom: (1.2.6 upstream) (4.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090412155430-plxucqyjjpl6aj3s
Tags: 0.16.0-3
Really upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
 
13
13
   This library is distributed in the hope that it will be useful,
14
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
16
   Lesser General Public License for more details.
17
17
 
18
18
   You should have received a copy of the GNU Lesser General Public
49
49
static int num_xshm_test_errors = 0;
50
50
 
51
51
static NSString *xshm_warning
52
 
        = @"Falling back to normal XImage: s (will be slower).";
 
52
        = @"Falling back to normal XImage: s (will be slower).";
53
53
 
54
54
static int test_xshm_error_handler(Display *d, XErrorEvent *ev)
55
55
{
57
57
  return 0;
58
58
}
59
59
 
60
 
static void test_xshm(Display *display, int drawing_depth)
 
60
static void test_xshm(Display *display, Visual *visual, int drawing_depth)
61
61
{
62
62
  NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
63
63
 
81
81
      return;
82
82
    }
83
83
 
 
84
  {
 
85
  int major, minor;
 
86
  Bool pixmaps;
 
87
 
 
88
  if (!XShmQueryVersion(display, &major, &minor, &pixmaps) || !pixmaps)
 
89
    {
 
90
      NSLog(@"XShm pixmaps not supported by X server.");
 
91
      NSLog(xshm_warning);
 
92
      use_xshm = 0;
 
93
      return;
 
94
    }
 
95
  }
 
96
 
84
97
  /* ... so we check that it actually works here. To do this, we need to
85
98
  set up our own error handler (because the xlib calls never fail, they
86
99
  just cause error events to be sent to us), explicitly synchronize
93
106
 
94
107
    old_error_handler = XSetErrorHandler(test_xshm_error_handler);
95
108
 
96
 
    ximage = XShmCreateImage(display,
97
 
        DefaultVisual(display, DefaultScreen(display)),
98
 
        drawing_depth, ZPixmap, NULL, &shminfo,
99
 
        1, 1);
 
109
    ximage = XShmCreateImage(display, visual,
 
110
                             drawing_depth, ZPixmap, NULL, &shminfo,
 
111
                             1, 1);
100
112
    XSync(display, False);
101
113
    if (!ximage || num_xshm_test_errors)
102
114
      {
103
 
        NSLog(@"XShm not supported, XShmCreateImage failed.");
104
 
        goto no_xshm;
 
115
        NSLog(@"XShm not supported, XShmCreateImage failed.");
 
116
        goto no_xshm;
105
117
      }
106
118
 
107
119
    shminfo.shmid = shmget(IPC_PRIVATE,
108
 
        64, /* We don't have exact bytes per row values here, but this
109
 
            should be safe, and we'll probably get a full page anyway.
110
 
            (And if it turns out not to be enough, the X server will notice
111
 
            and give us errors, causing us to think that XShm isn't
112
 
            supported.) */
113
 
        IPC_CREAT | 0700);
 
120
        64, /* We don't have exact bytes per row values here, but this
 
121
            should be safe, and we'll probably get a full page anyway.
 
122
             (And if it turns out not to be enough, the X server will notice
 
123
            and give us errors, causing us to think that XShm isn't
 
124
            supported.) */
 
125
        IPC_CREAT | 0700);
114
126
 
115
127
    if (shminfo.shmid == -1 || num_xshm_test_errors)
116
128
      {
117
 
        NSLog(@"XShm not supported, shmget() failed: %m.");
118
 
        XDestroyImage(ximage);
119
 
        goto no_xshm;
 
129
        NSLog(@"XShm not supported, shmget() failed: %m.");
 
130
        XDestroyImage(ximage);
 
131
        goto no_xshm;
120
132
      }
121
133
 
122
134
    shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
123
135
    if ((intptr_t)shminfo.shmaddr == -1 || num_xshm_test_errors)
124
136
      {
125
 
        NSLog(@"XShm not supported, shmat() failed: %m.");
126
 
        XDestroyImage(ximage);
127
 
        shmctl(shminfo.shmid, IPC_RMID, 0);
128
 
        goto no_xshm;
 
137
        NSLog(@"XShm not supported, shmat() failed: %m.");
 
138
        XDestroyImage(ximage);
 
139
        shmctl(shminfo.shmid, IPC_RMID, 0);
 
140
        goto no_xshm;
129
141
      }
130
142
 
131
143
    shminfo.readOnly = 0;
134
146
    XSync(display, False);
135
147
    if (num_xshm_test_errors)
136
148
      {
137
 
        NSLog(@"XShm not supported, XShmAttach() failed.");
138
 
        XDestroyImage(ximage);
139
 
        shmdt(shminfo.shmaddr);
140
 
        shmctl(shminfo.shmid, IPC_RMID, 0);
141
 
        goto no_xshm;
 
149
        NSLog(@"XShm not supported, XShmAttach() failed.");
 
150
        XDestroyImage(ximage);
 
151
        shmdt(shminfo.shmaddr);
 
152
        shmctl(shminfo.shmid, IPC_RMID, 0);
 
153
        goto no_xshm;
142
154
      }
143
155
 
144
156
    XShmDetach(display, &shminfo);
154
166
 
155
167
    if (num_xshm_test_errors)
156
168
      {
157
 
        NSLog(@"XShm not supported.");
 
169
        NSLog(@"XShm not supported.");
158
170
no_xshm: 
159
 
        NSLog(xshm_warning);
160
 
        use_xshm = 0;
 
171
        NSLog(xshm_warning);
 
172
        use_xshm = 0;
161
173
      }
162
174
    XSetErrorHandler(old_error_handler);
163
175
  }
166
178
 
167
179
@implementation XWindowBuffer
168
180
 
 
181
+ (void) initialize
 
182
{
 
183
  NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
 
184
  use_shape_hack = [ud boolForKey: @"XWindowBuffer-shape-hack"];
 
185
}
 
186
 
169
187
+ windowBufferForWindow: (gswindow_device_t *)awindow
170
188
              depthInfo: (struct XWindowBuffer_depth_info_s *)aDI
171
189
{
172
190
  int i;
173
191
  XWindowBuffer *wi;
 
192
  int drawing_depth;
 
193
  Visual *visual;
174
194
 
175
195
  for (i = 0; i < num_window_buffers; i++)
176
196
    {
177
197
      if (window_buffers[i]->window == awindow)
178
 
        break;
 
198
        break;
179
199
    }
180
200
  if (i == num_window_buffers)
181
201
    {
184
204
      window_buffers = realloc(window_buffers,
185
205
        sizeof(XWindowBuffer *) * (num_window_buffers + 1));
186
206
      if (!window_buffers)
187
 
        {
188
 
          NSLog(@"Out of memory (failed to allocate %i bytes)",
189
 
                sizeof(XWindowBuffer *) * (num_window_buffers + 1));
190
 
          exit(1);
191
 
        }
 
207
        {
 
208
          NSLog(@"Out of memory (failed to allocate %i bytes)",
 
209
                sizeof(XWindowBuffer *) * (num_window_buffers + 1));
 
210
          exit(1);
 
211
        }
192
212
      window_buffers[num_window_buffers++] = wi;
193
213
    }
194
214
  else
205
225
  wi->window->gdriverProtocol = GDriverHandlesExpose | GDriverHandlesBacking;
206
226
  wi->window->gdriver = wi;
207
227
 
 
228
#if 0
 
229
  drawing_depth = aDI->drawing_depth;
 
230
  visual = DefaultVisual(wi->display, DefaultScreen(wi->display));
 
231
#else
 
232
  // Better to get the used visual from the XGServer.
 
233
  visual = [(XGServer*)GSCurrentServer() visualForScreen: awindow->screen];
 
234
  drawing_depth = [(XGServer*)GSCurrentServer() depthForScreen: awindow->screen];
 
235
#endif
 
236
 
208
237
  /* TODO: resolve properly.
209
238
     -x11 is creating buffers before I have a chance to tell it not to, so
210
239
     I'm freeing them here to reduce memory consumption (and prevent
225
254
      wi->sx != awindow->xframe.size.width ||
226
255
      wi->sy != awindow->xframe.size.height)
227
256
    {
228
 
      wi->sx = wi->window->xframe.size.width;
229
 
/*              printf("%@ updating image for %p (%gx%g)\n", wi, wi->window,
230
 
                        wi->window->xframe.size.width, wi->window->xframe.size.height);*/
 
257
/*                printf("%@ updating image for %p (%gx%g)\n", wi, wi->window,
 
258
                        wi->window->xframe.size.width, wi->window->xframe.size.height);*/
231
259
      if (wi->ximage)
232
 
        {
233
 
          if (wi->use_shm)
234
 
            {
235
 
              XShmDetach(wi->display, &wi->shminfo);
236
 
              XDestroyImage(wi->ximage);
237
 
              shmdt(wi->shminfo.shmaddr);
238
 
            }
239
 
          else
240
 
            XDestroyImage(wi->ximage);
241
 
        }
 
260
        {
 
261
          if (wi->use_shm)
 
262
            {
 
263
              XShmDetach(wi->display, &wi->shminfo);
 
264
              XDestroyImage(wi->ximage);
 
265
              shmdt(wi->shminfo.shmaddr);
 
266
            }
 
267
          else
 
268
            XDestroyImage(wi->ximage);
 
269
        }
242
270
      if (wi->pixmap)
243
 
        {
244
 
          XFreePixmap(wi->display,wi->pixmap);
245
 
          XSetWindowBackground(wi->display,wi->window->ident,None);
246
 
          wi->pixmap=0;
247
 
        }
 
271
        {
 
272
          XFreePixmap(wi->display,wi->pixmap);
 
273
          XSetWindowBackground(wi->display,wi->window->ident,None);
 
274
          wi->pixmap=0;
 
275
        }
248
276
 
249
277
      wi->has_alpha = 0;
250
278
      if (wi->alpha)
251
 
        {
252
 
          free(wi->alpha);
253
 
          wi->alpha = NULL;
254
 
        }
 
279
        {
 
280
          free(wi->alpha);
 
281
          wi->alpha = NULL;
 
282
        }
255
283
 
256
284
      wi->pending_put = wi->pending_event = 0;
257
285
 
269
297
        goto no_xshm;
270
298
 
271
299
      if (!did_test_xshm)
272
 
        test_xshm(wi->display, aDI->drawing_depth);
 
300
        test_xshm(wi->display, visual, drawing_depth);
273
301
 
274
302
      if (!use_xshm)
275
303
        goto no_xshm;
276
304
 
277
305
      /* Use XShm if possible, else fall back to normal XImage: s */
278
306
      wi->use_shm = 1;
279
 
      wi->ximage = XShmCreateImage(wi->display,
280
 
        DefaultVisual(wi->display, DefaultScreen(wi->display)),
281
 
        aDI->drawing_depth, ZPixmap, NULL, &wi->shminfo,
282
 
        wi->window->xframe.size.width,
283
 
        wi->window->xframe.size.height);
 
307
      wi->ximage = XShmCreateImage(wi->display, visual,
 
308
                                   drawing_depth, ZPixmap, NULL, &wi->shminfo,
 
309
                                   wi->window->xframe.size.width,
 
310
                                   wi->window->xframe.size.height);
284
311
      if (!wi->ximage)
285
 
        {
286
 
          NSLog(@"Warning: XShmCreateImage failed!");
287
 
          NSLog(xshm_warning);
288
 
          goto no_xshm;
289
 
        }
 
312
        {
 
313
          NSLog(@"Warning: XShmCreateImage failed!");
 
314
          NSLog(xshm_warning);
 
315
          goto no_xshm;
 
316
        }
290
317
      wi->shminfo.shmid = shmget(IPC_PRIVATE,
291
 
        wi->ximage->bytes_per_line * wi->ximage->height,
292
 
        IPC_CREAT | 0700);
 
318
        wi->ximage->bytes_per_line * wi->ximage->height,
 
319
        IPC_CREAT | 0700);
293
320
 
294
321
      if (wi->shminfo.shmid == -1)
295
 
        {
296
 
          NSLog(@"Warning: shmget() failed: %m.");
297
 
          NSLog(xshm_warning);
298
 
          XDestroyImage(wi->ximage);
299
 
          goto no_xshm;
300
 
        }
 
322
        {
 
323
          NSLog(@"Warning: shmget() failed: %m.");
 
324
          NSLog(xshm_warning);
 
325
          XDestroyImage(wi->ximage);
 
326
          goto no_xshm;
 
327
        }
301
328
 
302
329
      wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
303
330
      if ((intptr_t)wi->shminfo.shmaddr == -1)
304
 
        {
305
 
          NSLog(@"Warning: shmat() failed: %m.");
306
 
          NSLog(xshm_warning);
307
 
          XDestroyImage(wi->ximage);
308
 
          shmctl(wi->shminfo.shmid, IPC_RMID, 0);
309
 
          goto no_xshm;
310
 
        }
 
331
        {
 
332
          NSLog(@"Warning: shmat() failed: %m.");
 
333
          NSLog(xshm_warning);
 
334
          XDestroyImage(wi->ximage);
 
335
          shmctl(wi->shminfo.shmid, IPC_RMID, 0);
 
336
          goto no_xshm;
 
337
        }
311
338
 
312
339
      wi->shminfo.readOnly = 0;
313
340
      if (!XShmAttach(wi->display, &wi->shminfo))
314
 
        {
315
 
          NSLog(@"Warning: XShmAttach() failed.");
316
 
          NSLog(xshm_warning);
317
 
          XDestroyImage(wi->ximage);
318
 
          shmdt(wi->shminfo.shmaddr);
319
 
          shmctl(wi->shminfo.shmid, IPC_RMID, 0);
320
 
          goto no_xshm;
321
 
        }
 
341
        {
 
342
          NSLog(@"Warning: XShmAttach() failed.");
 
343
          NSLog(xshm_warning);
 
344
          XDestroyImage(wi->ximage);
 
345
          shmdt(wi->shminfo.shmaddr);
 
346
          shmctl(wi->shminfo.shmid, IPC_RMID, 0);
 
347
          goto no_xshm;
 
348
        }
322
349
 
323
350
      /* We try to create a shared pixmap using the same buffer, and set
324
 
         it as the background of the window. This allows X to handle expose
325
 
         events all by itself, which avoids white flashing when things are
326
 
         dragged across a window. */
 
351
         it as the background of the window. This allows X to handle expose
 
352
         events all by itself, which avoids white flashing when things are
 
353
         dragged across a window. */
327
354
      /* TODO: we still get and handle expose events, although we don't
328
 
         need to. */
 
355
         need to. */
329
356
      wi->pixmap = XShmCreatePixmap(wi->display, wi->drawable,
330
 
                                    wi->ximage->data, &wi->shminfo,
331
 
                                    wi->window->xframe.size.width,
332
 
                                    wi->window->xframe.size.height,
333
 
                                    aDI->drawing_depth);
 
357
                                    wi->ximage->data, &wi->shminfo,
 
358
                                    wi->window->xframe.size.width,
 
359
                                    wi->window->xframe.size.height,
 
360
                                    drawing_depth);
334
361
      if (wi->pixmap) /* TODO: this doesn't work */
335
 
        {
336
 
          XSetWindowBackgroundPixmap(wi->display, wi->window->ident,
337
 
                                     wi->pixmap);
338
 
        }
 
362
        {
 
363
          XSetWindowBackgroundPixmap(wi->display, wi->window->ident,
 
364
                                     wi->pixmap);
 
365
        }
339
366
 
340
367
      /* On some systems (eg. freebsd), X can't attach to the shared segment
341
368
      if it's marked for destruction, so we make sure it's attached before
348
375
      shmctl(wi->shminfo.shmid, IPC_RMID, 0);
349
376
 
350
377
      if (!wi->ximage)
351
 
        {
 
378
        {
352
379
no_xshm: 
353
 
          wi->use_shm = 0;
354
 
          wi->ximage = XCreateImage(wi->display, DefaultVisual(wi->display,
355
 
            DefaultScreen(wi->display)), aDI->drawing_depth, ZPixmap, 0, NULL,
356
 
            wi->window->xframe.size.width, wi->window->xframe.size.height,
357
 
            8, 0);
 
380
          wi->use_shm = 0;
 
381
          wi->ximage = XCreateImage(wi->display, visual, drawing_depth, 
 
382
                                    ZPixmap, 0, NULL,
 
383
                                    wi->window->xframe.size.width, 
 
384
                                    wi->window->xframe.size.height,
 
385
                                    8, 0);
358
386
 
359
 
          wi->ximage->data = malloc(wi->ximage->height * wi->ximage->bytes_per_line);
360
 
          if (!wi->ximage->data)
361
 
            {
362
 
              XDestroyImage(wi->ximage);
363
 
              wi->ximage = NULL;
364
 
            }
365
 
/*TODO? wi->ximage = XGetImage(wi->display, wi->drawable,
366
 
                0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
367
 
                -1, ZPixmap);*/
368
 
        }
 
387
          wi->ximage->data = malloc(wi->ximage->height * wi->ximage->bytes_per_line);
 
388
          if (!wi->ximage->data)
 
389
            {
 
390
              XDestroyImage(wi->ximage);
 
391
              wi->ximage = NULL;
 
392
            }
 
393
/*TODO?        wi->ximage = XGetImage(wi->display, wi->drawable,
 
394
                0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
 
395
                -1, ZPixmap);*/
 
396
        }
369
397
    }
370
398
 
371
399
  if (wi->ximage)
376
404
      wi->bytes_per_line = wi->ximage->bytes_per_line;
377
405
      wi->bits_per_pixel = wi->ximage->bits_per_pixel;
378
406
      wi->bytes_per_pixel = wi->bits_per_pixel / 8;
379
 
//              NSLog(@"%@ ximage=%p data=%p\n", wi->ximage, wi->data);
 
407
//                NSLog(@"%@ ximage=%p data=%p\n", wi->ximage, wi->data);
380
408
    }
381
409
  else
382
410
    {
400
428
    {
401
429
      pending_put = 0;
402
430
      if (pending_rect.x + pending_rect.w > window->xframe.size.width)
403
 
        {
404
 
          pending_rect.w = window->xframe.size.width - pending_rect.x;
405
 
          if (pending_rect.w <= 0)
406
 
            return;
407
 
        }
 
431
        {
 
432
          pending_rect.w = window->xframe.size.width - pending_rect.x;
 
433
          if (pending_rect.w <= 0)
 
434
            return;
 
435
        }
408
436
      if (pending_rect.y + pending_rect.h > window->xframe.size.height)
409
 
        {
410
 
          pending_rect.h = window->xframe.size.height - pending_rect.y;
411
 
          if (pending_rect.h <= 0)
412
 
            return;
413
 
        }
 
437
        {
 
438
          pending_rect.h = window->xframe.size.height - pending_rect.y;
 
439
          if (pending_rect.h <= 0)
 
440
            return;
 
441
        }
414
442
      if (!XShmPutImage(display, drawable, gc, ximage,
415
 
                        pending_rect.x, pending_rect.y,
416
 
                        pending_rect.x, pending_rect.y,
417
 
                        pending_rect.w, pending_rect.h,
418
 
                        1))
419
 
        {
420
 
          NSLog(@"XShmPutImage failed?");
421
 
        }
 
443
                        pending_rect.x, pending_rect.y,
 
444
                        pending_rect.x, pending_rect.y,
 
445
                        pending_rect.w, pending_rect.h,
 
446
                        1))
 
447
        {
 
448
          NSLog(@"XShmPutImage failed?");
 
449
        }
422
450
      else
423
 
        {
424
 
          pending_event = 1;
425
 
        }
 
451
        {
 
452
          pending_event = 1;
 
453
        }
426
454
    }
427
 
//      XFlush(window->display);
 
455
//        XFlush(window->display);
428
456
}
429
457
 
430
458
- (void) _exposeRect: (NSRect)rect
476
504
    {
477
505
 
478
506
      /* HACK: lets try to use shaped windows to get some use out of
479
 
         destination alpha */
 
507
         destination alpha */
480
508
      if (has_alpha && use_shape_hack)
481
 
        {
 
509
        {
482
510
static int warn = 0;
483
 
          Pixmap p;
484
 
          int dsize = ((sx + 7) / 8) * sy;
485
 
          unsigned char *buf = malloc(dsize);
486
 
          unsigned char *dst;
487
 
          int bofs;
488
 
          unsigned char *a;
489
 
          int as;
490
 
          int i, x;
491
 
 
492
 
          if (!warn)
493
 
            NSLog(@"Warning: activating shaped windows");
494
 
          warn = 1;
495
 
 
496
 
          memset(buf, 0xff, dsize);
 
511
          Pixmap p;
 
512
          int dsize = ((sx + 7) / 8) * sy;
 
513
          unsigned char *buf = malloc(dsize);
 
514
          unsigned char *dst;
 
515
          int bofs;
 
516
          unsigned char *a;
 
517
          int as;
 
518
          int i, x;
 
519
 
 
520
          if (!warn)
 
521
            NSLog(@"Warning: activating shaped windows");
 
522
          warn = 1;
 
523
 
 
524
          memset(buf, 0xff, dsize);
497
525
 
498
526
#define CUTOFF 128
499
527
 
500
 
          if (DI.inline_alpha)
501
 
            {
502
 
              a = data + DI.inline_alpha_ofs;
503
 
              as = DI.bytes_per_pixel;
504
 
            }
505
 
          else
506
 
            {
507
 
              a = alpha;
508
 
              as = 1;
509
 
            }
 
528
          if (DI.inline_alpha)
 
529
            {
 
530
              a = data + DI.inline_alpha_ofs;
 
531
              as = DI.bytes_per_pixel;
 
532
            }
 
533
          else
 
534
            {
 
535
              a = alpha;
 
536
              as = 1;
 
537
            }
510
538
 
511
 
          for (bofs = 0, i = sx * sy, x = sx, dst = buf; i; i--, a += as)
512
 
            {
513
 
              if (*a < CUTOFF)
514
 
                {
515
 
                  *dst = *dst & ~(1 << bofs);
516
 
                }
517
 
              bofs++;
518
 
              if (bofs == 8)
519
 
                {
520
 
                  dst++;
521
 
                  bofs = 0;
522
 
                }
523
 
              x--;
524
 
              if (!x)
525
 
                {
526
 
                  if (bofs)
527
 
                    {
528
 
                      bofs = 0;
529
 
                      dst++;
530
 
                    }
531
 
                  x = sx;
532
 
                }
533
 
            }
 
539
          for (bofs = 0, i = sx * sy, x = sx, dst = buf; i; i--, a += as)
 
540
            {
 
541
              if (*a < CUTOFF)
 
542
                {
 
543
                  *dst = *dst & ~(1 << bofs);
 
544
                }
 
545
              bofs++;
 
546
              if (bofs == 8)
 
547
                {
 
548
                  dst++;
 
549
                  bofs = 0;
 
550
                }
 
551
              x--;
 
552
              if (!x)
 
553
                {
 
554
                  if (bofs)
 
555
                    {
 
556
                      bofs = 0;
 
557
                      dst++;
 
558
                    }
 
559
                  x = sx;
 
560
                }
 
561
            }
534
562
#undef CUTOFF
535
563
//NSLog(@"check shape");
536
 
          if (old_shape_size == dsize && !memcmp(old_shape, buf, dsize))
537
 
            {
538
 
              free(buf);
539
 
//              NSLog(@"  same shape");
540
 
            }
541
 
          else
542
 
            {
543
 
//              NSLog(@"  updating");
544
 
              p = XCreatePixmapFromBitmapData(display, window->ident,
545
 
                                              (char *)buf, sx, sy, 1, 0, 1);
546
 
              free(old_shape);
547
 
              old_shape = buf;
548
 
              old_shape_size = dsize;
549
 
              XShapeCombineMask(display, window->ident,
550
 
                                ShapeBounding, 0, 0, p, ShapeSet);
551
 
              XFreePixmap(display, p);
552
 
            }
553
 
        }
 
564
          if (old_shape_size == dsize && !memcmp(old_shape, buf, dsize))
 
565
            {
 
566
              free(buf);
 
567
//                NSLog(@"  same shape");
 
568
            }
 
569
          else
 
570
            {
 
571
//                NSLog(@"  updating");
 
572
              p = XCreatePixmapFromBitmapData(display, window->ident,
 
573
                                              (char *)buf, sx, sy, 1, 0, 1);
 
574
              free(old_shape);
 
575
              old_shape = buf;
 
576
              old_shape_size = dsize;
 
577
              XShapeCombineMask(display, window->ident,
 
578
                                ShapeBounding, 0, 0, p, ShapeSet);
 
579
              XFreePixmap(display, p);
 
580
            }
 
581
        }
554
582
 
555
583
      if (pending_event)
556
 
        {
557
 
          if (!pending_put)
558
 
            {
559
 
              pending_put = 1;
560
 
              pending_rect.x = x;
561
 
              pending_rect.y = y;
562
 
              pending_rect.w = w;
563
 
              pending_rect.h = h;
564
 
            }
565
 
          else
566
 
            {
567
 
              if (x < pending_rect.x)
568
 
                {
569
 
                  pending_rect.w += pending_rect.x - x;
570
 
                  pending_rect.x = x;
571
 
                }
572
 
              if (x + w > pending_rect.x + pending_rect.w)
573
 
                {
574
 
                  pending_rect.w = x + w - pending_rect.x;
575
 
                }
576
 
              if (y < pending_rect.y)
577
 
                {
578
 
                  pending_rect.h += pending_rect.y - y;
579
 
                  pending_rect.y = y;
580
 
                }
581
 
              if (y + h > pending_rect.y + pending_rect.h)
582
 
                {
583
 
                  pending_rect.h = y + h - pending_rect.y;
584
 
                }
585
 
            }
586
 
        }
 
584
        {
 
585
          if (!pending_put)
 
586
            {
 
587
              pending_put = 1;
 
588
              pending_rect.x = x;
 
589
              pending_rect.y = y;
 
590
              pending_rect.w = w;
 
591
              pending_rect.h = h;
 
592
            }
 
593
          else
 
594
            {
 
595
              if (x < pending_rect.x)
 
596
                {
 
597
                  pending_rect.w += pending_rect.x - x;
 
598
                  pending_rect.x = x;
 
599
                }
 
600
              if (x + w > pending_rect.x + pending_rect.w)
 
601
                {
 
602
                  pending_rect.w = x + w - pending_rect.x;
 
603
                }
 
604
              if (y < pending_rect.y)
 
605
                {
 
606
                  pending_rect.h += pending_rect.y - y;
 
607
                  pending_rect.y = y;
 
608
                }
 
609
              if (y + h > pending_rect.y + pending_rect.h)
 
610
                {
 
611
                  pending_rect.h = y + h - pending_rect.y;
 
612
                }
 
613
            }
 
614
        }
587
615
      else
588
 
        {
589
 
          pending_put = 0;
590
 
          if (!XShmPutImage(display, drawable, gc, ximage,
591
 
                            x, y, x, y, w, h, 1))
592
 
            {
593
 
              NSLog(@"XShmPutImage failed?");
594
 
            }
595
 
          else
596
 
            {
597
 
              pending_event = 1;
598
 
            }
599
 
        }
 
616
        {
 
617
          pending_put = 0;
 
618
          if (!XShmPutImage(display, drawable, gc, ximage,
 
619
                            x, y, x, y, w, h, 1))
 
620
            {
 
621
              NSLog(@"XShmPutImage failed?");
 
622
            }
 
623
          else
 
624
            {
 
625
              pending_event = 1;
 
626
            }
 
627
        }
600
628
 
601
629
      /* Performance hack. Check right away for ShmCompletion
602
 
         events. */
 
630
         events. */
603
631
      {
604
 
        XEvent e;
 
632
        XEvent e;
605
633
 
606
 
        while (XCheckTypedEvent(window->display,
607
 
          XShmGetEventBase(window->display) + ShmCompletion, &e))
608
 
          {
609
 
            [isa _gotShmCompletion: ((XShmCompletionEvent *)&e)->drawable];
610
 
          }
 
634
        while (XCheckTypedEvent(window->display,
 
635
          XShmGetEventBase(window->display) + ShmCompletion, &e))
 
636
          {
 
637
            [isa _gotShmCompletion: ((XShmCompletionEvent *)&e)->drawable];
 
638
          }
611
639
      }
612
640
    }
613
641
  else if (ximage)
624
652
  if (!data)
625
653
    return;
626
654
 
627
 
//      NSLog(@"needs alpha for %p: %ix%i", self, sx, sy);
 
655
//        NSLog(@"needs alpha for %p: %ix%i", self, sx, sy);
628
656
 
629
657
  if (DI.inline_alpha)
630
658
    {
634
662
      has_alpha = 1;
635
663
      /* fill the alpha channel */
636
664
      for (i = 0, s = data + DI.inline_alpha_ofs; i < sx * sy;
637
 
           i++, s += DI.bytes_per_pixel)
638
 
        *s = 0xff;
 
665
           i++, s += DI.bytes_per_pixel)
 
666
        *s = 0xff;
639
667
      return;
640
668
    }
641
669
 
646
674
      return;
647
675
    }
648
676
 
649
 
//      NSLog(@"got buffer at %p", alpha);
 
677
//        NSLog(@"got buffer at %p", alpha);
650
678
 
651
679
  has_alpha = 1;
652
680
  memset(alpha, 0xff, sx * sy);
662
690
    {
663
691
      num_window_buffers--;
664
692
      for (; i < num_window_buffers; i++)
665
 
        window_buffers[i] = window_buffers[i + 1];
 
693
        window_buffers[i] = window_buffers[i + 1];
666
694
    }
667
695
 
668
696
  if (ximage)
669
697
    {
670
698
      if (pixmap)
671
 
        {
672
 
          XFreePixmap(display,pixmap);
673
 
          pixmap=0;
674
 
        }
 
699
        {
 
700
          XFreePixmap(display,pixmap);
 
701
          pixmap=0;
 
702
        }
675
703
 
676
704
      if (use_shm)
677
 
        {
678
 
          XShmDetach(display, &shminfo);
679
 
          XDestroyImage(ximage);
680
 
          shmdt(shminfo.shmaddr);
681
 
        }
 
705
        {
 
706
          XShmDetach(display, &shminfo);
 
707
          XDestroyImage(ximage);
 
708
          shmdt(shminfo.shmaddr);
 
709
        }
682
710
      else
683
 
        XDestroyImage(ximage);
 
711
        XDestroyImage(ximage);
684
712
    }
685
713
  if (alpha)
686
714
    free(alpha);
688
716
}
689
717
 
690
718
 
691
 
+ (void) initialize
692
 
{
693
 
  NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
694
 
  use_shape_hack = [ud boolForKey: @"XWindowBuffer-shape-hack"];
695
 
}
696
 
 
697
 
 
698
719
+ (void) _gotShmCompletion: (Drawable)d
699
720
{
700
721
  int i;
701
722
  for (i = 0; i < num_window_buffers; i++)
702
723
    {
703
724
      if (window_buffers[i]->drawable == d)
704
 
        {
705
 
          [window_buffers[i] _gotShmCompletion];
706
 
          return;
707
 
        }
 
725
        {
 
726
          [window_buffers[i] _gotShmCompletion];
 
727
          return;
 
728
        }
708
729
    }
709
730
}
710
731