29 #include <pango/pangocairo.h> 33 static size_t g_nextContextId = 1;
35 DirtyRectangle::DirtyRectangle() : m_X(~0), m_Y(~0), m_X2(0), m_Y2(0)
39 DirtyRectangle::~DirtyRectangle()
43 void DirtyRectangle::point(
size_t x,
size_t y)
56 void WObject::reposition(
size_t x,
size_t y,
size_t w,
size_t h)
59 x = m_Dimensions.getX();
61 y = m_Dimensions.getY();
63 w = m_Dimensions.getW();
65 h = m_Dimensions.getH();
67 m_Dimensions.update(x, y, w, h);
72 void WObject::bump(ssize_t bumpX, ssize_t bumpY)
74 size_t x = m_Dimensions.getX() + bumpX;
75 size_t y = m_Dimensions.getY() + bumpY;
76 size_t w = m_Dimensions.getW();
77 size_t h = m_Dimensions.getH();
78 m_Dimensions.update(x, y, w, h);
82 uint64_t handle,
int sock,
struct sockaddr *sa,
size_t sa_len,
84 : m_Handle(handle), m_pParent(pParent), m_Framebuffer(0), m_Dirty(),
85 m_bPendingDecoration(false), m_bFocus(false), m_bRefresh(true),
86 m_nRegionWidth(0), m_nRegionHeight(0), m_Socket(sock), m_Sa(sa),
90 m_pParent->addChild(
this);
109 m_bPendingDecoration =
true;
110 klog(LOG_DEBUG,
"not refreshing context, marking for redecoration");
114 if ((me.getW() < WINDOW_CLIENT_LOST_W) ||
115 (me.getH() < WINDOW_CLIENT_LOST_H))
119 LOG_DEBUG,
"extents %ux%u are too small for a new context",
120 me.getW(), me.getH());
124 klog(LOG_DEBUG,
"destroying old framebuffer...");
125 delete m_Framebuffer;
127 klog(LOG_DEBUG,
"destroying old framebuffer complete");
130 size_t regionWidth = me.getW() - WINDOW_CLIENT_LOST_W;
131 size_t regionHeight = me.getH() - WINDOW_CLIENT_LOST_H;
133 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, regionWidth);
134 size_t regionSize = regionHeight * stride;
136 memset(m_Framebuffer->getBuffer(), 0, regionSize);
139 LOG_DEBUG,
"new framebuffer created: %zd bytes @%p", regionSize,
140 m_Framebuffer->getBuffer());
142 m_nRegionWidth = regionWidth;
143 m_nRegionHeight = regionHeight;
145 if ((m_Socket >= 0) && m_Framebuffer)
149 char *buffer =
new char[totalSize];
150 memset(buffer, 0, totalSize);
162 pReposition->
rt.update(0, 0, regionWidth, regionHeight);
167 sendMessage(buffer, totalSize);
172 m_bPendingDecoration =
true;
175 void *Window::getFramebuffer()
const 177 return m_Framebuffer ? m_Framebuffer->getBuffer() : 0;
180 void Window::sendMessage(
const char *msg,
size_t len)
182 sendto(m_Socket, msg, len, 0, m_Sa, m_SaLen);
189 size_t realX = dirty.getX();
190 size_t realY = dirty.getY();
191 size_t realW = dirty.getW();
192 size_t realH = dirty.getH();
194 size_t clientW = me.getW() - WINDOW_CLIENT_LOST_W;
195 size_t clientH = me.getH() - WINDOW_CLIENT_LOST_H;
197 if (realX > clientW || realY > clientH)
202 if ((realX + realW) > clientW)
204 realW = clientW - realX;
207 if ((realY + realH) > clientH)
209 realH = clientH - realY;
213 realX + WINDOW_CLIENT_START_X, realY + WINDOW_CLIENT_START_Y, realW,
217 void Window::render(cairo_t *cr)
221 size_t x = me.getX() + WINDOW_BORDER_X;
222 size_t y = me.getY() + WINDOW_BORDER_Y;
223 size_t w = me.getW() - (WINDOW_BORDER_X * 2);
224 size_t h = me.getH() - (WINDOW_BORDER_Y * 2);
227 void *pBuffer = getFramebuffer();
228 if (pBuffer && (isDirty() && m_bRefresh))
231 size_t regionWidth = m_nRegionWidth;
232 size_t regionHeight = m_nRegionHeight;
234 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, regionWidth);
236 cairo_surface_t *surface = cairo_image_surface_create_for_data(
237 (uint8_t *) pBuffer, CAIRO_FORMAT_ARGB32, regionWidth, regionHeight,
241 size_t dirtyX = realDirty.getX();
242 size_t dirtyY = realDirty.getY();
243 size_t dirtyWidth = realDirty.getW();
244 size_t dirtyHeight = realDirty.getH();
247 if (dirtyX < WINDOW_CLIENT_START_X)
249 dirtyX = WINDOW_CLIENT_START_X;
251 if (dirtyY < WINDOW_CLIENT_START_Y)
253 dirtyY = WINDOW_CLIENT_START_Y;
255 if ((dirtyX + dirtyWidth) > regionWidth)
257 dirtyWidth = regionWidth;
259 if ((dirtyY + dirtyHeight) > regionHeight)
261 dirtyHeight = regionHeight;
265 realDirty.update(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
267 cairo_set_source_surface(
268 cr, surface, me.getX() + WINDOW_CLIENT_START_X,
269 me.getY() + WINDOW_CLIENT_START_Y);
273 cr, me.getX() + realDirty.getX(), me.getY() + realDirty.getY(),
274 realDirty.getW(), realDirty.getH());
279 cr, me.getX() + WINDOW_CLIENT_START_X,
280 me.getY() + WINDOW_CLIENT_START_Y, me.getW() - WINDOW_CLIENT_LOST_W,
281 me.getH() - WINDOW_CLIENT_LOST_H);
287 cairo_surface_destroy(surface);
291 m_Dirty.update(0, 0, 0, 0);
298 memset(&ackmsg, 0,
sizeof(ackmsg));
303 sendMessage((
const char *) &ackmsg,
sizeof(ackmsg));
306 if (m_bPendingDecoration)
308 double r = 0.0, g = 0.0, b = 0.0;
311 else if (m_pParent->getFocusWindow() ==
this)
318 PangoLayout *layout = pango_cairo_create_layout(cr);
319 PangoFontDescription *desc =
320 pango_font_description_from_string(WINMAN_PANGO_FONT);
321 pango_layout_set_font_description(layout, desc);
322 pango_font_description_free(desc);
324 gchar *safe_markup = g_markup_escape_text(m_sWindowTitle.c_str(), -1);
325 pango_layout_set_markup(layout, safe_markup, -1);
328 cairo_set_line_width(cr, 0);
329 cairo_set_source_rgba(cr, 0.2, 0.3, 0.3, 1.0);
330 cairo_rectangle(cr, x, y, w, WINDOW_TITLE_H);
333 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
334 cairo_set_source_rgba(cr, 0.7, 0.7, 0.7, 1.0);
337 int width = 0, height = 0;
338 pango_layout_get_size(layout, &width, &height);
339 cairo_move_to(cr, x + ((w / 2) - ((width / PANGO_SCALE) / 2)), y);
340 pango_cairo_show_layout(cr, layout);
343 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
344 cairo_set_source_rgba(cr, r, g, b, 1.0);
345 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
346 cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
347 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
348 cairo_set_line_width(cr, 1.0);
350 cairo_rectangle(cr, x, y, w, h);
353 g_object_unref(layout);
358 m_bPendingDecoration =
false;
364 m_pParent->setFocusWindow(
this);
365 m_bPendingDecoration =
true;
369 memset(pHeader, 0,
sizeof(*pHeader));
375 sendMessage((
const char *) pHeader,
sizeof(*pHeader));
379 void Window::nofocus()
382 m_bPendingDecoration =
true;
386 memset(pHeader, 0,
sizeof(*pHeader));
392 sendMessage((
const char *) pHeader,
sizeof(*pHeader));
397 ssize_t horizDistance, ssize_t vertDistance,
WObject *pChild)
400 size_t currentWidth = me.getW();
401 size_t currentHeight = me.getH();
404 me.getX(), me.getY(), currentWidth + horizDistance,
405 currentHeight + vertDistance);
409 m_pParent->resize(horizDistance, vertDistance,
this);
411 m_bPendingDecoration =
true;
416 if (m_Children.size() == 0)
418 klog(LOG_INFO,
"winman: no children in container, no retile");
423 size_t currentWidth = me.getW();
424 size_t currentHeight = me.getH();
426 if (m_Layout == SideBySide)
428 size_t dividedW = currentWidth / m_Children.size();
429 size_t newX = me.getX();
430 size_t newY = me.getY();
432 WObjectList_t::iterator it = m_Children.begin();
433 for (; it != m_Children.end(); ++it)
435 (*it)->reposition(newX, newY, dividedW, currentHeight);
439 else if (m_Layout == Stacked)
441 size_t dividedH = currentHeight / m_Children.size();
442 size_t newX = me.getX();
443 size_t newY = me.getY();
445 WObjectList_t::iterator it = m_Children.begin();
446 for (; it != m_Children.end(); ++it)
448 (*it)->reposition(newX, newY, currentWidth, dividedH);
454 WObjectList_t::iterator it = m_Children.begin();
455 for (; it != m_Children.end(); ++it)
457 if ((*it)->getType() == WObject::Container ||
458 (*it)->getType() == WObject::Root)
467 ssize_t horizDistance, ssize_t vertDistance,
WObject *pChild)
470 size_t currentWidth = me.getW();
471 size_t currentHeight = me.getH();
475 ssize_t bumpX = horizDistance;
476 ssize_t bumpY = vertDistance;
478 horizDistance = -horizDistance;
479 vertDistance = -vertDistance;
481 WObjectList_t::iterator it = m_Children.begin();
482 bool bResize =
false;
483 for (; it != m_Children.end(); ++it)
487 (*it)->bump(bumpX, bumpY);
488 (*it)->resize(horizDistance, vertDistance);
499 klog(LOG_INFO,
"winman: didn't find children for resize???");
504 me.getX(), me.getY(), currentWidth + horizDistance,
505 currentHeight + vertDistance);
507 if (m_Children.size())
515 horizDistance /
static_cast<ssize_t
>(m_Children.size());
517 vertDistance /
static_cast<ssize_t
>(m_Children.size());
520 WObjectList_t::iterator it = m_Children.begin();
522 for (; it != m_Children.end(); ++it)
524 if (m_Layout == Stacked)
526 (*it)->resize(horizDistance, extendH);
528 else if (m_Layout == SideBySide)
530 (*it)->bump(bumpX, 0);
531 (*it)->resize(extendW, vertDistance);
540 if (m_pParent && ((m_pParent->getType() == WObject::Container) ||
541 m_pParent->getType() == WObject::Root))
546 horizDistance, vertDistance, static_cast<WObject *>(
this));
552 WObjectList_t::iterator it = m_Children.begin();
553 for (; it != m_Children.end(); ++it)
555 if ((*it)->getType() == WObject::Container)
560 else if ((*it)->getType() == WObject::Window)
570 WObjectList_t::const_iterator it = m_Children.begin();
571 for (; it != m_Children.end(); ++it)
575 if (it == m_Children.begin())
590 WObjectList_t::const_iterator it = m_Children.begin();
591 for (; it != m_Children.end(); ++it)
597 if (it == m_Children.end())
611 return getLeftSibling(
this);
616 return getRightSibling(
this);
622 if (m_Layout == SideBySide)
624 WObject *sibling = getLeftSibling(obj);
633 if (m_pParent && (m_pParent->getType() == WObject::Container))
636 if (pContainer->getLayout() == SideBySide)
638 sibling = getLeftObject();
647 if (getType() != WObject::Root)
650 return pContainer->
getLeft(
this);
659 if (m_Layout == SideBySide)
661 WObject *sibling = getRightSibling(obj);
670 if (m_pParent && (m_pParent->getType() == WObject::Container))
673 if (pContainer->getLayout() == SideBySide)
675 sibling = getRightObject();
684 if (getType() != WObject::Root)
696 if (m_Layout == Stacked)
698 WObject *sibling = getLeftSibling(obj);
707 if (m_pParent && (m_pParent->getType() == WObject::Container))
710 if (pContainer->getLayout() == Stacked)
712 sibling = getLeftObject();
721 if (getType() != WObject::Root)
724 return pContainer->
getUp(
this);
733 if (m_Layout == Stacked)
735 WObject *sibling = getRightSibling(obj);
744 if (m_pParent && (m_pParent->getType() == WObject::Container))
747 if (pContainer->getLayout() == Stacked)
749 sibling = getRightObject();
758 if (getType() != WObject::Root)
761 return pContainer->
getDown(
this);
768 ssize_t horizDistance, ssize_t vertDistance,
WObject *pChild)
781 WObjectList_t::const_iterator it = m_Children.begin();
782 for (; it != m_Children.end(); ++it)
791 WObjectList_t::const_iterator it = m_Children.begin();
792 for (; it != m_Children.end(); ++it)
PedigreeGraphics::Rect rt
New rect.
WObject * getRightSibling(const WObject *pChild) const
virtual void yesrefresh()
Refresh context on every reposition.
void * shmem_handle
New handle for the shared memory space.
WObject * getLeftSibling(const WObject *pChild) const
WObject * getDown(const WObject *obj) const
virtual void refreshContext()
Refresh our graphical context, called after reposition.
Abstracts a buffer shared between multiple processes.
handle_t widgetHandle
Handle for the widget being referred to. Zero if no widget.
size_t messageSize
Size of the data in the message (after this header).
WObject * getRight(const WObject *obj) const
size_t shmem_size
Size of the framebuffer.
WObject * getLeft(const WObject *obj) const
MessageIdentifiers messageCode
Code of the message being sent.
virtual void norefresh()
Don't refresh the context on every reposition.
virtual void resize(ssize_t horizDistance, ssize_t vertDistance, WObject *pChild=0)
virtual void resize(ssize_t horizDistance, ssize_t vertDistance, WObject *pChild=0)
WObject * getUp(const WObject *obj) const
WObject * getRightObject() const
bool isResponse
Whether this message is a response from the window manager or not.
WObject * getLeftObject() const