]> icculus.org git repositories - mikachu/openbox.git/blob - src/frame.cc
readd titlebar buttons. but they dont press yet
[mikachu/openbox.git] / src / frame.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 extern "C" {
6 #ifdef    SHAPE
7 #include <X11/extensions/shape.h>
8 #endif // SHAPE
9 }
10
11 #include "frame.hh"
12 #include "client.hh"
13 #include "openbox.hh"
14 #include "otk/display.hh"
15 #include "otk/surface.hh"
16
17 #include <string>
18 #include <cassert>
19
20 namespace ob {
21
22 const long Frame::event_mask;
23
24 Window createWindow(const otk::ScreenInfo *info, Window parent, 
25                     unsigned long mask, XSetWindowAttributes *attrib)
26 {
27   return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0,
28                        info->depth(), InputOutput, info->visual(),
29                        mask, attrib);
30                        
31 }
32
33 Frame::Frame(Client *client)
34   : _client(client),
35     _visible(false),
36     _plate(0),
37     _title(0),
38     _label(0),
39     _handle(0),
40     _lgrip(0),
41     _rgrip(0),
42     _max(0),
43     _desk(0),
44     _iconify(0),
45     _icon(0),
46     _close(0),
47     _frame_sur(0),
48     _title_sur(0),
49     _label_sur(0),
50     _handle_sur(0),
51     _grip_sur(0),
52     _max_sur(0),
53     _desk_sur(0),
54     _iconify_sur(0),
55     _icon_sur(0),
56     _close_sur(0),
57     _max_press(false),
58     _desk_press(false),
59     _iconify_press(false),
60     _icon_press(false),
61     _close_press(false)
62 {
63   assert(client);
64
65   XSetWindowAttributes attrib;
66   unsigned long mask;
67   const otk::ScreenInfo *info = otk::display->screenInfo(client->screen());
68
69   // create all of the decor windows (except title bar buttons)
70   mask = CWOverrideRedirect | CWEventMask;
71   attrib.event_mask = Frame::event_mask;
72   attrib.override_redirect = true;
73   _frame = createWindow(info, info->rootWindow(), mask, &attrib);
74
75   mask = 0;
76   _plate = createWindow(info, _frame, mask, &attrib);
77   mask = CWEventMask;
78   attrib.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
79                        ExposureMask);
80   _title = createWindow(info, _frame, mask, &attrib);
81   _label = createWindow(info, _title, mask, &attrib);
82   _max = createWindow(info, _title, mask, &attrib);
83   _close = createWindow(info, _title, mask, &attrib);
84   _desk = createWindow(info, _title, mask, &attrib);
85   _icon = createWindow(info, _title, mask, &attrib);
86   _iconify = createWindow(info, _title, mask, &attrib);
87   _handle = createWindow(info, _frame, mask, &attrib);
88   mask |= CWCursor;
89   attrib.cursor = openbox->cursors().ll_angle;
90   _lgrip = createWindow(info, _handle, mask, &attrib);
91   attrib.cursor = openbox->cursors().lr_angle;
92   _rgrip = createWindow(info, _handle, mask, &attrib);
93
94   // the other stuff is shown based on decor settings
95   XMapWindow(**otk::display, _plate);
96   XMapWindow(**otk::display, _lgrip);
97   XMapWindow(**otk::display, _rgrip);
98   XMapWindow(**otk::display, _label);
99
100   applyStyle(*otk::RenderStyle::style(_client->screen()));
101
102   _layout = "NDITMC";
103
104   // register all of the windows with the event dispatcher
105   Window *w = allWindows();
106   for (unsigned int i = 0; w[i]; ++i)
107     openbox->registerHandler(w[i], this);
108   delete [] w;
109 }
110
111 Frame::~Frame()
112 {
113   // unregister all of the windows with the event dispatcher
114   Window *w = allWindows();
115   for (unsigned int i = 0; w[i]; ++i)
116     openbox->clearHandler(w[i]);
117   delete [] w;
118
119   XDestroyWindow(**otk::display, _rgrip);
120   XDestroyWindow(**otk::display, _lgrip);
121   XDestroyWindow(**otk::display, _handle);
122   XDestroyWindow(**otk::display, _max);
123   XDestroyWindow(**otk::display, _icon);
124   XDestroyWindow(**otk::display, _iconify);
125   XDestroyWindow(**otk::display, _desk);
126   XDestroyWindow(**otk::display, _close);
127   XDestroyWindow(**otk::display, _label);
128   XDestroyWindow(**otk::display, _title);
129   XDestroyWindow(**otk::display, _frame);
130
131   if (_frame_sur) delete _frame_sur;
132   if (_title_sur) delete _title_sur;
133   if (_label_sur) delete _label_sur;
134   if (_handle_sur) delete _handle_sur;
135   if (_grip_sur) delete _grip_sur;
136   if (_max_sur) delete _max_sur;
137   if (_desk_sur) delete _desk_sur;
138   if (_iconify_sur) delete _iconify_sur;
139   if (_icon_sur) delete _icon_sur;
140   if (_close_sur) delete _close_sur;
141 }
142
143 void Frame::show()
144 {
145   if (!_visible) {
146     _visible = true;
147     XMapWindow(**otk::display, _frame);
148   }
149 }
150
151 void Frame::hide()
152 {
153   if (_visible) {
154     _visible = false;
155     XUnmapWindow(**otk::display, _frame);
156   }
157 }
158
159 MouseContext::MC Frame::mouseContext(Window win) const
160 {
161   if (win == _frame)  return MouseContext::Frame;
162   if (win == _title ||
163       win == _label)  return MouseContext::Titlebar;
164   if (win == _handle) return MouseContext::Handle;
165   if (win == _plate)  return MouseContext::Window;
166   if (win == _lgrip ||
167       win == _rgrip)  return MouseContext::Grip;
168   if (win == _max)    return MouseContext::MaximizeButton;
169   if (win == _close)  return MouseContext::CloseButton;
170   if (win == _desk)   return MouseContext::AllDesktopsButton;
171   if (win == _iconify)return MouseContext::IconifyButton;
172   if (win == _icon)   return MouseContext::IconButton;
173   return (MouseContext::MC) -1;
174 }
175
176 Window *Frame::allWindows() const
177 {
178   Window *w = new Window[12 + 1];
179   unsigned int i = 0;
180   w[i++] = _frame;
181   w[i++] = _plate;
182   w[i++] = _title;
183   w[i++] = _label;
184   w[i++] = _handle;
185   w[i++] = _lgrip;
186   w[i++] = _rgrip;
187   w[i++] = _max;
188   w[i++] = _desk;
189   w[i++] = _close;
190   w[i++] = _icon;
191   w[i++] = _iconify;
192   w[i] = 0;
193   return w;
194 }
195
196 void Frame::applyStyle(const otk::RenderStyle &style)
197 {
198   // set static border colors
199   XSetWindowBorder(**otk::display, _frame, style.frameBorderColor()->pixel());
200   XSetWindowBorder(**otk::display, _title, style.frameBorderColor()->pixel());
201   XSetWindowBorder(**otk::display, _handle, style.frameBorderColor()->pixel());
202   XSetWindowBorder(**otk::display, _lgrip, style.frameBorderColor()->pixel());
203   XSetWindowBorder(**otk::display, _rgrip, style.frameBorderColor()->pixel());
204
205   // size all the fixed-size elements
206   geom.font_height = style.labelFont()->height();
207   if (geom.font_height < 1) geom.font_height = 1;
208   geom.button_size = geom.font_height - 2;
209   if (geom.button_size < 1) geom.button_size = 1;
210   geom.handle_height = style.handleWidth();
211   if (geom.handle_height < 1) geom.handle_height = 1;
212   geom.bevel = style.bevelWidth();
213   
214   XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height);
215   XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height);
216   
217   XResizeWindow(**otk::display, _max, geom.button_size, geom.button_size);
218   XResizeWindow(**otk::display, _close, geom.button_size, geom.button_size);
219   XResizeWindow(**otk::display, _desk, geom.button_size, geom.button_size);
220   XResizeWindow(**otk::display, _iconify, geom.button_size, geom.button_size);
221   XResizeWindow(**otk::display, _icon, geom.button_size, geom.button_size);
222 }
223
224 void Frame::styleChanged(const otk::RenderStyle &style)
225 {
226   applyStyle(style);
227   
228   // size/position everything
229   adjustSize();
230   adjustPosition();
231 }
232
233 void Frame::adjustFocus()
234 {
235   // XXX optimizations later...
236   adjustSize();
237 }
238
239 void Frame::adjustTitle()
240 {
241   // XXX optimizations later...
242   adjustSize();
243 }
244
245 static void render(int screen, const otk::Size &size, Window win,
246                    otk::Surface **surface,
247                    const otk::RenderTexture &texture, bool freedata=true)
248 {
249   otk::Surface *s = new otk::Surface(screen, size);
250   otk::display->renderControl(screen)->drawBackground(*s, texture);
251   XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
252   XClearWindow(**otk::display, win);
253   if (*surface) delete *surface;
254   if (freedata) s->freePixelData();
255   *surface = s;
256 }
257
258 void Frame::adjustSize()
259 {
260   Client::DecorationFlags decorations = _client->decorations();
261   const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
262
263   if (decorations & Client::Decor_Border) {
264     geom.bwidth = style->frameBorderWidth();
265     geom.cbwidth = style->clientBorderWidth();
266   } else {
267     geom.bwidth = geom.cbwidth = 0;
268   }
269   _innersize.left = _innersize.top = _innersize.bottom = _innersize.right =
270     geom.cbwidth;
271   geom.width = _client->area().width() + geom.cbwidth * 2;
272   assert(geom.width > 0);
273
274   // set border widths
275   XSetWindowBorderWidth(**otk::display, _plate, geom.cbwidth);
276   XSetWindowBorderWidth(**otk::display, _frame, geom.bwidth);
277   XSetWindowBorderWidth(**otk::display, _title, geom.bwidth);
278   XSetWindowBorderWidth(**otk::display, _handle, geom.bwidth);
279   XSetWindowBorderWidth(**otk::display, _lgrip, geom.bwidth);
280   XSetWindowBorderWidth(**otk::display, _rgrip, geom.bwidth);
281   
282   // position/size and map/unmap all the windows
283
284   if (decorations & Client::Decor_Titlebar) {
285     XMoveResizeWindow(**otk::display, _title, -geom.bwidth, -geom.bwidth,
286                       geom.width, geom.title_height());
287     _innersize.top += geom.title_height() + geom.bwidth;
288     XMapWindow(**otk::display, _title);
289
290     // layout the title bar elements
291     layoutTitle();
292   } else
293     XUnmapWindow(**otk::display, _title);
294
295   if (decorations & Client::Decor_Handle) {
296     geom.handle_y = _innersize.top + _client->area().height() + geom.cbwidth;
297     XMoveResizeWindow(**otk::display, _handle, -geom.bwidth, geom.handle_y,
298                       geom.width, geom.handle_height);
299     XMoveWindow(**otk::display, _lgrip, -geom.bwidth, -geom.bwidth);
300     XMoveWindow(**otk::display, _rgrip,
301                 -geom.bwidth + geom.width - geom.grip_width(),
302                 -geom.bwidth);
303     _innersize.bottom += geom.handle_height + geom.bwidth;
304     XMapWindow(**otk::display, _handle);
305   } else
306     XUnmapWindow(**otk::display, _handle);
307   
308   XResizeWindow(**otk::display, _frame, geom.width,
309                 (_client->shaded() ? geom.title_height() :
310                  _innersize.top + _innersize.bottom +
311                  _client->area().height()));
312
313   // do this in two steps because clients whose gravity is set to
314   // 'Static' don't end up getting moved at all with an XMoveResizeWindow
315   XMoveWindow(**otk::display, _plate, _innersize.left - geom.cbwidth,
316               _innersize.top - geom.cbwidth);
317   XResizeWindow(**otk::display, _plate, _client->area().width(),
318                 _client->area().height());
319
320   _size.left   = _innersize.left + geom.bwidth;
321   _size.right  = _innersize.right + geom.bwidth;
322   _size.top    = _innersize.top + geom.bwidth;
323   _size.bottom = _innersize.bottom + geom.bwidth;
324
325   _area = otk::Rect(_area.position(), otk::Size(_client->area().width() +
326                                                 _size.left + _size.right,
327                                                 _client->area().height() +
328                                                 _size.top + _size.bottom));
329
330   // render all the elements
331   int screen = _client->screen();
332   bool focus = _client->focused();
333   if (decorations & Client::Decor_Titlebar) {
334     render(screen, otk::Size(geom.width, geom.title_height()), _title,
335            &_title_sur, *(focus ? style->titlebarFocusBackground() :
336                           style->titlebarUnfocusBackground()), false);
337     
338     renderLabel();
339     renderMax();
340     renderDesk();
341     renderIconify();
342     renderIcon();
343     renderClose();
344   }
345
346   if (decorations & Client::Decor_Handle) {
347     render(screen, otk::Size(geom.width, geom.handle_height), _handle,
348            &_handle_sur, *(focus ? style->handleFocusBackground() :
349                            style->handleUnfocusBackground()));
350     render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip,
351            &_grip_sur, *(focus ? style->gripFocusBackground() :
352                          style->gripUnfocusBackground()));
353     XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap());
354     XClearWindow(**otk::display, _rgrip);
355   }
356
357   XSetWindowBorder(**otk::display, _plate,
358                    focus ? style->clientBorderFocusColor()->pixel() :
359                    style->clientBorderUnfocusColor()->pixel());
360   
361   adjustShape();
362 }
363
364 void Frame::renderLabel()
365 {
366   const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
367   const otk::RenderControl *control =
368     otk::display->renderControl(_client->screen());
369   const otk::Font *font = style->labelFont();
370
371   otk::Surface *s = new otk::Surface(_client->screen(),
372                                      otk::Size(geom.label_width,
373                                                geom.label_height()));
374   control->drawBackground(*s, *(_client->focused() ?
375                                 style->labelFocusBackground() :
376                                 style->labelUnfocusBackground()));
377
378   otk::ustring t = _client->title(); // the actual text to draw
379   int x = geom.bevel;                // x coord for the text
380
381   if (x * 2 > geom.label_width) return; // no room at all
382
383   // find a string that will fit inside the area for text
384   otk::ustring::size_type text_len = t.size();
385   int length;
386   int maxsize = geom.label_width - geom.bevel * 2;
387       
388   do {
389     t.resize(text_len);
390     length = font->measureString(t);  // this returns an unsigned, so check < 0
391     if (length < 0) length = maxsize; // if the string's that long just adjust
392   } while (length > maxsize && text_len-- > 0);
393
394   if (text_len <= 0) return; // won't fit anything
395
396   // justify the text
397   switch (style->labelTextJustify()) {
398   case otk::RenderStyle::RightBottomJustify:
399     x += maxsize - length;
400     break;
401   case otk::RenderStyle::CenterJustify:
402     x += (maxsize - length) / 2;
403     break;
404   case otk::RenderStyle::LeftTopJustify:
405     break;
406   }
407  
408   control->drawString(*s, *font, x, 0,
409                       *(_client->focused() ? style->textFocusColor() :
410                         style->textUnfocusColor()), t);
411
412   XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap());
413   XClearWindow(**otk::display, _label);
414   if (_label_sur) delete _label_sur;
415   s->freePixelData();
416   _label_sur = s;
417 }
418
419 static void renderButton(int screen, bool focus, bool press, Window win,
420                          otk::Surface **sur, int butsize,
421                          const otk::PixmapMask *mask)
422 {
423   const otk::RenderStyle *style = otk::RenderStyle::style(screen);
424   const otk::RenderControl *control = otk::display->renderControl(screen);
425   otk::Surface *s = new otk::Surface(screen, otk::Size(butsize, butsize));
426
427   const otk::RenderTexture *tx = (focus ?
428                                   (press ?
429                                    style->buttonPressFocusBackground() :
430                                    style->buttonUnpressFocusBackground()) :
431                                   (press ?
432                                    style->buttonPressUnfocusBackground() :
433                                    style->buttonUnpressUnfocusBackground()));
434   const otk::RenderColor *maskcolor = (focus ?
435                                        style->buttonFocusColor() :
436                                        style->buttonUnfocusColor());
437   control->drawBackground(*s, *tx);
438   control->drawMask(*s, *maskcolor, *mask);
439
440   XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
441   XClearWindow(**otk::display, win);
442   if (*sur) delete *sur;
443   *sur = s;
444 }
445
446 void Frame::renderMax()
447 {
448   renderButton(_client->screen(), _client->focused(), _max_press, _max,
449                &_max_sur, geom.button_size,
450                otk::RenderStyle::style(_client->screen())->maximizeMask());
451 }
452
453 void Frame::renderDesk()
454 {
455   renderButton(_client->screen(), _client->focused(), _desk_press, _desk,
456                &_desk_sur, geom.button_size,
457                otk::RenderStyle::style(_client->screen())->alldesktopsMask());
458 }
459
460 void Frame::renderIconify()
461 {
462   renderButton(_client->screen(), _client->focused(), _iconify_press, _iconify,
463                &_iconify_sur, geom.button_size,
464                otk::RenderStyle::style(_client->screen())->iconifyMask());
465 }
466
467 void Frame::renderClose()
468 {
469   renderButton(_client->screen(), _client->focused(), _close_press, _close,
470                &_close_sur, geom.button_size,
471                otk::RenderStyle::style(_client->screen())->closeMask());
472 }
473
474 void Frame::renderIcon()
475 {
476   const int screen = _client->screen();
477   const otk::RenderControl *control = otk::display->renderControl(screen);
478
479   otk::Surface *s = new otk::Surface(screen, otk::Size(geom.button_size,
480                                                        geom.button_size));
481   otk::pixel32 *dest = s->pixelData(), *src;
482   int w = _title_sur->size().width();
483   
484   src = _title_sur->pixelData() + w * (geom.bevel + 1) + geom.icon_x;
485   
486   // get the background under the icon button
487   for (int y = 0; y < geom.button_size; ++y, src += w - geom.button_size)
488     for (int x = 0; x < geom.button_size; ++x, ++dest, ++src)
489       *dest = *src;
490   control->drawImage(*s, 0, 0, 0);
491
492   XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap());
493   XClearWindow(**otk::display, _icon);
494   if (_icon_sur) delete _icon_sur;
495   _icon_sur = s;
496 }
497
498 void Frame::layoutTitle()
499 {
500   geom.label_width = geom.width - geom.bevel * 2 -
501     (geom.button_size + geom.bevel) * (_layout.size() - 1);
502   if (geom.label_width < 1) geom.label_width = 1;
503
504   XResizeWindow(**otk::display, _label, geom.label_width, geom.font_height);
505   
506   int x = geom.bevel;
507   bool n, d, i, l, m ,c;
508   n = d = i = l = m = c = false;
509   for (const char *lc = _layout.c_str(); *lc; ++lc) {
510     switch (*lc) {
511     case 'n':
512     case 'N':
513       geom.icon_x = x;
514       XMapWindow(**otk::display, _icon);
515       XMoveWindow(**otk::display, _icon, x, geom.bevel + 1);
516       n = true;
517       x += geom.button_size;
518       break;
519     case 'd':
520     case 'D':
521       XMapWindow(**otk::display, _desk);
522       XMoveWindow(**otk::display, _desk, x, geom.bevel + 1);
523       d = true;
524       x += geom.button_size;
525       break;
526     case 'i':
527     case 'I':
528       XMapWindow(**otk::display, _iconify);
529       XMoveWindow(**otk::display, _iconify, x, geom.bevel + 1);
530       i = true;
531       x += geom.button_size;
532       break;
533     case 't':
534     case 'T':
535       XMapWindow(**otk::display, _label);
536       XMoveWindow(**otk::display, _label, x, geom.bevel);
537       l = true;
538       x += geom.label_width;
539       break;
540     case 'm':
541     case 'M':
542       XMapWindow(**otk::display, _max);
543       XMoveWindow(**otk::display, _max, x, geom.bevel + 1);
544       m = true;
545       x += geom.button_size;
546       break;
547     case 'c':
548     case 'C':
549       XMapWindow(**otk::display, _close);
550       XMoveWindow(**otk::display, _close, x, geom.bevel + 1);
551       c = true;
552       x += geom.button_size;
553       break;
554     }
555     x += geom.bevel;
556   }
557   if (!n) XUnmapWindow(**otk::display, _icon);
558   if (!d) XUnmapWindow(**otk::display, _desk);
559   if (!i) XUnmapWindow(**otk::display, _iconify);
560   if (!l) XUnmapWindow(**otk::display, _label);
561   if (!m) XUnmapWindow(**otk::display, _max);
562   if (!c) XUnmapWindow(**otk::display, _close);
563 }
564
565 void Frame::adjustPosition()
566 {
567   int x, y;
568   x = _client->area().x();
569   y = _client->area().y();
570   clientGravity(x, y);
571   XMoveWindow(**otk::display, _frame, x, y);
572   _area = otk::Rect(otk::Point(x, y), _area.size());
573 }
574
575
576 void Frame::adjustShape()
577 {
578 #ifdef SHAPE
579   Client::DecorationFlags decorations = _client->decorations();
580   
581   if (!_client->shaped()) {
582     // clear the shape on the frame window
583     XShapeCombineMask(**otk::display, _frame, ShapeBounding,
584                       _innersize.left,
585                       _innersize.top,
586                       None, ShapeSet);
587   } else {
588     // make the frame's shape match the clients
589     XShapeCombineShape(**otk::display, _frame, ShapeBounding,
590                        _innersize.left,
591                        _innersize.top,
592                        _client->window(), ShapeBounding, ShapeSet);
593
594     int num = 0;
595     XRectangle xrect[2];
596
597     if (decorations & Client::Decor_Titlebar) {
598       xrect[0].x = -geom.bevel;
599       xrect[0].y = -geom.bevel;
600       xrect[0].width = geom.width + geom.bwidth * 2;
601       xrect[0].height = geom.title_height() + geom.bwidth * 2;
602       ++num;
603     }
604
605     if (decorations & Client::Decor_Handle) {
606       xrect[1].x = -geom.bevel;
607       xrect[1].y = geom.handle_y;
608       xrect[1].width = geom.width + geom.bwidth * 2;
609       xrect[1].height = geom.handle_height + geom.bwidth * 2;
610       ++num;
611     }
612
613     XShapeCombineRectangles(**otk::display, _frame,
614                             ShapeBounding, 0, 0, xrect, num,
615                             ShapeUnion, Unsorted);
616   }
617 #endif // SHAPE
618 }
619
620
621 void Frame::adjustState()
622 {
623 // XXX  _button_alldesk.update();
624 // XXX  _button_max.update();
625 }
626
627
628 void Frame::grabClient()
629 {
630   // reparent the client to the frame
631   XReparentWindow(**otk::display, _client->window(), _plate, 0, 0);
632   /*
633     When reparenting the client window, it is usually not mapped yet, since
634     this occurs from a MapRequest. However, in the case where Openbox is
635     starting up, the window is already mapped, so we'll see unmap events for
636     it. There are 2 unmap events generated that we see, one with the 'event'
637     member set the root window, and one set to the client, but both get handled
638     and need to be ignored.
639   */
640   if (openbox->state() == Openbox::State_Starting)
641     _client->ignore_unmaps += 2;
642
643   // select the event mask on the client's parent (to receive config/map req's)
644   XSelectInput(**otk::display, _plate, SubstructureRedirectMask);
645
646   // map the client so it maps when the frame does
647   XMapWindow(**otk::display, _client->window());
648
649   adjustSize();
650   adjustPosition();
651 }
652
653
654 void Frame::releaseClient()
655 {
656   XEvent ev;
657
658   // check if the app has already reparented its window away
659   if (XCheckTypedWindowEvent(**otk::display, _client->window(),
660                              ReparentNotify, &ev)) {
661     XPutBackEvent(**otk::display, &ev);
662     // re-map the window since the unmanaging process unmaps it
663     XMapWindow(**otk::display, _client->window());  
664   } else {
665     // according to the ICCCM - if the client doesn't reparent itself, then we
666     // will reparent the window to root for them
667     XReparentWindow(**otk::display, _client->window(),
668                     otk::display->screenInfo(_client->screen())->rootWindow(),
669                     _client->area().x(), _client->area().y());
670   }
671 }
672
673
674 void Frame::clientGravity(int &x, int &y)
675 {
676   // horizontal
677   switch (_client->gravity()) {
678   default:
679   case NorthWestGravity:
680   case SouthWestGravity:
681   case WestGravity:
682     break;
683
684   case NorthGravity:
685   case SouthGravity:
686   case CenterGravity:
687     x -= (_size.left + _size.right) / 2;
688     break;
689
690   case NorthEastGravity:
691   case SouthEastGravity:
692   case EastGravity:
693     x -= _size.left + _size.right;
694     break;
695
696   case ForgetGravity:
697   case StaticGravity:
698     x -= _size.left;
699     break;
700   }
701
702   // vertical
703   switch (_client->gravity()) {
704   default:
705   case NorthWestGravity:
706   case NorthEastGravity:
707   case NorthGravity:
708     break;
709
710   case CenterGravity:
711   case EastGravity:
712   case WestGravity:
713     y -= (_size.top + _size.bottom) / 2;
714     break;
715
716   case SouthWestGravity:
717   case SouthEastGravity:
718   case SouthGravity:
719     y -= _size.top + _size.bottom;
720     break;
721
722   case ForgetGravity:
723   case StaticGravity:
724     y -= _size.top;
725     break;
726   }
727 }
728
729
730 void Frame::frameGravity(int &x, int &y)
731 {
732   // horizontal
733   switch (_client->gravity()) {
734   default:
735   case NorthWestGravity:
736   case WestGravity:
737   case SouthWestGravity:
738     break;
739   case NorthGravity:
740   case CenterGravity:
741   case SouthGravity:
742     x += (_size.left + _size.right) / 2;
743     break;
744   case NorthEastGravity:
745   case EastGravity:
746   case SouthEastGravity:
747     x += _size.left + _size.right;
748     break;
749   case StaticGravity:
750   case ForgetGravity:
751     x += _size.left;
752     break;
753   }
754
755   // vertical
756   switch (_client->gravity()) {
757   default:
758   case NorthWestGravity:
759   case WestGravity:
760   case SouthWestGravity:
761     break;
762   case NorthGravity:
763   case CenterGravity:
764   case SouthGravity:
765     y += (_size.top + _size.bottom) / 2;
766     break;
767   case NorthEastGravity:
768   case EastGravity:
769   case SouthEastGravity:
770     y += _size.top + _size.bottom;
771     break;
772   case StaticGravity:
773   case ForgetGravity:
774     y += _size.top;
775     break;
776   }
777 }
778
779
780 }