1
// Tab.cc for Fluxbox Window Manager
2
// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
4
// Permission is hereby granted, free of charge, to any person obtaining a
5
// copy of this software and associated documentation files (the "Software"),
6
// to deal in the Software without restriction, including without limitation
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
// and/or sell copies of the Software, and to permit persons to whom the
9
// Software is furnished to do so, subject to the following conditions:
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
// DEALINGS IN THE SOFTWARE.
22
// $Id: Tab.cc,v 1.20 2002/02/04 06:50:48 fluxgen Exp $
27
# include "../config.h"
28
#endif // HAVE_CONFIG_H
31
#include "DrawUtil.hh"
37
bool Tab::m_stoptabs = false;
38
Tab::t_tabplacementlist Tab::m_tabplacementlist[] = {
46
Tab::t_tabplacementlist Tab::m_tabalignmentlist[] = {
50
{ARELATIVE, "Relative"},
54
Tab::Tab(FluxboxWindow *win, Tab *prev, Tab *next) {
57
m_focus = m_moving = false;
58
m_configured = true; // only set to false before Fluxbox::reconfigure
59
m_move_x = m_move_y = 0;
60
m_prev = prev; m_next = next;
62
m_display = Fluxbox::instance()->getXDisplay();
64
if ((m_win->getScreen()->getTabPlacement() == PLEFT ||
65
m_win->getScreen()->getTabPlacement() == PRIGHT) &&
66
m_win->getScreen()->isTabRotateVertical()) {
67
m_size_w = m_win->getScreen()->getTabHeight();
68
m_size_h = m_win->getScreen()->getTabWidth();
70
m_size_w = m_win->getScreen()->getTabWidth();
71
m_size_h = m_win->getScreen()->getTabHeight();
83
Fluxbox::instance()->removeTabSearch(m_tabwin);
84
XDestroyWindow(m_display, m_tabwin);
88
//---------------- createTabWindow ---------------
90
// Creates the Window for tab to be above the title window.
91
// This should only be called by the constructor.
92
//-------------------------------------------------
93
void Tab::createTabWindow() {
94
unsigned long attrib_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
95
CWColormap | CWOverrideRedirect | CWEventMask;
96
XSetWindowAttributes attrib;
97
attrib.background_pixmap = None;
98
attrib.background_pixel = attrib.border_pixel =
99
m_win->getScreen()->getWindowStyle()->tab.border_color.getPixel();
100
attrib.colormap = m_win->getScreen()->getColormap();
101
attrib.override_redirect = True;
102
attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
103
ButtonMotionMask | ExposureMask | EnterWindowMask;
104
//Notice that m_size_w gets the TOTAL width of tabs INCLUDING borders
105
m_tabwin = XCreateWindow(m_display, m_win->getScreen()->getRootWindow(),
106
-30000, -30000, //TODO: So that it wont flicker or
107
// appear before the window do
108
m_size_w - m_win->getScreen()->getWindowStyle()->tab.border_width_2x,
109
m_size_h - m_win->getScreen()->getWindowStyle()->tab.border_width_2x,
110
m_win->getScreen()->getWindowStyle()->tab.border_width,
111
m_win->getScreen()->getDepth(), InputOutput,
112
m_win->getScreen()->getVisual(), attrib_mask, &attrib);
115
XGrabButton(m_display, Button1, Mod1Mask, m_tabwin, True,
116
ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
117
GrabModeAsync, None, Fluxbox::instance()->getMoveCursor());
120
Fluxbox::instance()->saveTabSearch(m_tabwin, this);
122
XMapSubwindows(m_display, m_tabwin);
124
XMapWindow(m_display, m_tabwin);
129
//-------------- focus --------------------
130
// Called when the focus changes in m_win
131
// updates pixmap or color and draws the tab
132
//-----------------------------------------
135
if (m_win->isFocused()) {
137
XSetWindowBackgroundPixmap(m_display, m_tabwin, m_focus_pm);
139
XSetWindowBackground(m_display, m_tabwin, m_focus_pixel);
142
XSetWindowBackgroundPixmap(m_display, m_tabwin, m_unfocus_pm);
144
XSetWindowBackground(m_display, m_tabwin, m_unfocus_pixel);
146
XClearWindow(m_display, m_tabwin);
150
//-------------- raise --------------------
151
// Raises the tabs in the tablist
152
//-----------------------------------------
157
for (tab = getFirst(this); tab!=0; tab = tab->m_next)
158
m_win->getScreen()->raiseWindows(&tab->m_tabwin, 1);
161
//-------------- lower --------------------
162
// Lowers the tabs in the tablist AND
163
// the windows the tabs relate to
164
//-----------------------------------------
167
FluxboxWindow *win = 0; //convenience
168
//this have to be done in the correct order, otherwise we'll switch the window
169
//being ontop in the group
171
XLowerWindow(m_display, current->m_tabwin); //lower tabwin and tabs window
172
win = current->getWindow();
173
win->getScreen()->getWorkspace(win->getWorkspaceNumber())->lowerWindow(win);
175
current = current->next(); //get next
177
current = getFirst(this); //there weren't any after, get the first
179
} while (current != this);
182
//-------------- loadTheme -----------------
183
// loads the texture with the correct
184
// width and height, this is necessary in
185
// vertical and relative tab modes
186
// TODO optimize this
187
//------------------------------------------
188
void Tab::loadTheme() {
189
BImageControl *image_ctrl = m_win->getScreen()->getImageControl();
190
Pixmap tmp = m_focus_pm;
191
BTexture *texture = &(m_win->getScreen()->getWindowStyle()->tab.l_focus);
193
if (texture->getTexture() & BImage::PARENTRELATIVE ) {
194
BTexture *pt = &(m_win->getScreen()->getWindowStyle()->tab.t_focus);
195
if (pt->getTexture() == (BImage::FLAT | BImage::SOLID)) {
197
m_focus_pixel = pt->getColor()->getPixel();
200
image_ctrl->renderImage(m_size_w, m_size_h, pt);
202
if (tmp) image_ctrl->removeImage(tmp);
205
if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) {
207
m_focus_pixel = texture->getColor()->getPixel();
210
image_ctrl->renderImage(m_size_w, m_size_h, texture);
211
if (tmp) image_ctrl->removeImage(tmp);
215
texture = &(m_win->getScreen()->getWindowStyle()->tab.l_unfocus);
217
if (texture->getTexture() & BImage::PARENTRELATIVE ) {
218
BTexture *pt = &(m_win->getScreen()->getWindowStyle()->tab.t_unfocus);
219
if (pt->getTexture() == (BImage::FLAT | BImage::SOLID)) {
221
m_unfocus_pixel = pt->getColor()->getPixel();
224
image_ctrl->renderImage(m_size_w, m_size_h, pt);
226
if (texture->getTexture() == (BImage::FLAT | BImage::SOLID)) {
228
m_unfocus_pixel = texture->getColor()->getPixel();
231
image_ctrl->renderImage(m_size_w, m_size_h, texture);
234
if (tmp) image_ctrl->removeImage(tmp);
237
//-------------- decorate --------------------
238
// decorates the tab with current theme
239
//--------------------------------------------
240
void Tab::decorate() {
243
XSetWindowBorderWidth(m_display, m_tabwin,
244
m_win->getScreen()->getWindowStyle()->tab.border_width);
245
XSetWindowBorder(m_display, m_tabwin,
246
m_win->getScreen()->getWindowStyle()->tab.border_color.getPixel());
249
//-------------- deiconify -----------------
250
// Deiconifies the tab
251
// Used from FluxboxWindow to deiconify the tab when the window is deiconfied
252
//------------------------------------------
253
void Tab::deiconify() {
254
XMapWindow(m_display, m_tabwin);
257
//------------- iconify --------------------
258
// Iconifies the tab.
259
// Used from FluxboxWindow to hide tab win when window is iconified
260
// disconnects itself from the list
261
//------------------------------------------
262
void Tab::iconify() {
267
//------------ withdraw --------------
268
// Unmaps the tab from display
269
//------------------------------------
270
void Tab::withdraw() {
271
XUnmapWindow(m_display, m_tabwin);
274
//------------ stick --------------------
275
// Set/reset the the sticky on all windows in the list
276
//---------------------------------------
280
//now do stick for all windows in the list
281
for (tab = getFirst(this); tab != 0; tab = tab->m_next) {
282
FluxboxWindow *win = tab->m_win; //just for convenience
283
if (win->isStuck()) {
284
win->blackbox_attrib.flags ^= BaseDisplay::ATTRIB_OMNIPRESENT;
285
win->blackbox_attrib.attrib ^= BaseDisplay::ATTRIB_OMNIPRESENT;
287
if (!win->isIconic())
288
win->getScreen()->reassociateWindow(win, -1, true);
292
win->blackbox_attrib.flags |= BaseDisplay::ATTRIB_OMNIPRESENT;
293
win->blackbox_attrib.attrib |= BaseDisplay::ATTRIB_OMNIPRESENT;
296
win->setState(win->current_state);
301
//------------- resize -------------
302
// Resize the window's in the tablist
303
//----------------------------------
307
//now move and resize the windows in the list
308
for (tab = getFirst(this); tab != 0; tab = tab->m_next) {
310
tab->m_win->configure(m_win->getXFrame(), m_win->getYFrame(),
311
m_win->getWidth(), m_win->getHeight());
315
// need to resize tabs if in relative mode
316
if (m_win->getScreen()->getTabAlignment() == ARELATIVE) {
322
//----------- shade --------------
323
// Shades the windows in the tablist
324
//--------------------------------
328
for(tab = getFirst(this); tab != 0; tab = tab->m_next) {
334
if (m_win->getScreen()->getTabPlacement() == PLEFT ||
335
m_win->getScreen()->getTabPlacement() == PRIGHT) {
340
if (!(m_win->getScreen()->getTabPlacement() == PTOP))
344
//------------ draw -----------------
346
// if pressed = true then it draws the tab in pressed
347
// mode else it draws it in normal mode
348
// TODO: the "draw in pressed mode"
349
//-----------------------------------
350
void Tab::draw(bool pressed) {
351
unsigned int tabtext_w;
353
GC gc = ((m_win->isFocused()) ? m_win->getScreen()->getWindowStyle()->tab.l_text_focus_gc :
354
m_win->getScreen()->getWindowStyle()->tab.l_text_unfocus_gc);
356
// Different routines for drawing rotated text
357
if ((m_win->getScreen()->getTabPlacement() == PLEFT ||
358
m_win->getScreen()->getTabPlacement() == PRIGHT) &&
359
(!m_win->isShaded() && m_win->getScreen()->isTabRotateVertical())) {
361
tabtext_w = DrawUtil::XRotTextWidth(m_win->getScreen()->getWindowStyle()->tab.rot_font,
362
m_win->client.title, m_win->client.title_len);
363
tabtext_w += (m_win->frame.bevel_w * 4);
365
DrawUtil::DrawRotString(m_display, m_tabwin, gc,
366
m_win->getScreen()->getWindowStyle()->tab.rot_font,
367
m_win->getScreen()->getWindowStyle()->tab.font.justify,
368
tabtext_w, m_size_w, m_size_h,
369
m_win->frame.bevel_w, m_win->client.title);
372
if (I18n::instance()->multibyte()) { // TODO: maybe move this out from here?
373
XRectangle ink, logical;
374
XmbTextExtents(m_win->getScreen()->getWindowStyle()->tab.font.set,
375
m_win->client.title, m_win->client.title_len,
377
tabtext_w = logical.width;
379
tabtext_w = XTextWidth(
380
m_win->getScreen()->getWindowStyle()->tab.font.fontstruct,
381
m_win->client.title, m_win->client.title_len);
383
tabtext_w += (m_win->frame.bevel_w * 4);
385
DrawUtil::DrawString(m_display, m_tabwin, gc,
386
&m_win->getScreen()->getWindowStyle()->tab.font,
388
m_win->frame.bevel_w, m_win->client.title);
392
//-----------------------------------------------
393
//Helper for the Tab::setPosition() call
394
//returns the y position component correctly
395
//according to shading in cases PBOTTOM and
397
//-----------------------------------------------
398
int Tab::setPositionShadingHelper(bool shaded) {
400
return m_win->getYFrame() + m_win->getTitleHeight() +
401
m_win->getScreen()->getBorderWidth2x();
403
return m_win->getYFrame() + m_win->getHeight() +
404
m_win->getScreen()->getBorderWidth2x();
408
//-----------------------------------------------
409
//Helpers for correct alignment of tabs used
410
//by the setPosition() call
411
//return x/y positions correctly according to
412
//alignment, the 1st for cases PTOP and PBOTTOM
413
//the 2nd for cases PLEFT and PRIGHT
414
//-----------------------------------------------
415
int Tab::setPositionTBAlignHelper(Alignment align) {
420
return m_win->getXFrame();
423
return calcCenterXPos();
426
return m_win->getXFrame() + m_win->getWidth() +
427
m_win->getScreen()->getBorderWidth2x() - m_size_w;
430
cerr << __FILE__ << ":" <<__LINE__ << ": " <<
431
"Unsupported Alignment" << endl;
438
int Tab::setPositionLRAlignHelper(Alignment align) {
441
return m_win->getYFrame() - m_size_h + m_win->getHeight() +
442
m_win->getScreen()->getBorderWidth2x();
445
return calcCenterYPos();
449
return m_win->getYFrame();
453
cerr << __FILE__ << ":"<< __LINE__ << ": " <<
454
"Unsupported Alignment" << endl;
461
//------------- setPosition -----------------
462
// Position tab ( follow the m_win pos ).
464
// Set new position of the other tabs in the chain
465
//-------------------------------------------
466
void Tab::setPosition() {
467
//don't do anything if the tablist is freezed
472
int pos_x = 0, pos_y = 0;
474
m_stoptabs = true; //freeze tablist
476
//and check for max tabs
478
//Tab placement + alignment
479
switch (m_win->getScreen()->getTabPlacement()) {
481
pos_y = m_win->getYFrame() - m_size_h;
482
pos_x = setPositionTBAlignHelper(
483
m_win->getScreen()->getTabAlignment());
486
pos_y = setPositionShadingHelper(m_win->isShaded());
487
pos_x = setPositionTBAlignHelper(
488
m_win->getScreen()->getTabAlignment());
491
pos_x = m_win->isShaded() ?
492
setPositionTBAlignHelper(m_win->getScreen()->getTabAlignment()) :
493
m_win->getXFrame() - m_size_w;
494
pos_y = m_win->isShaded() ?
495
setPositionShadingHelper(true) :
496
setPositionLRAlignHelper(m_win->getScreen()->getTabAlignment());
499
pos_x = m_win->isShaded() ?
500
setPositionTBAlignHelper(m_win->getScreen()->getTabAlignment()) :
501
m_win->getXFrame() + m_win->getWidth() +
502
m_win->getScreen()->getBorderWidth2x();
503
pos_y = m_win->isShaded() ?
504
setPositionShadingHelper(true) :
505
setPositionLRAlignHelper(m_win->getScreen()->getTabAlignment());
508
if(m_win->isShaded()) {
509
pos_y = setPositionShadingHelper(true);
510
pos_x = setPositionTBAlignHelper(
511
m_win->getScreen()->getTabAlignment());
513
setPositionShadingHelper(false);
518
for (tab = getFirst(this);
520
pos_x += tab->m_inc_x, pos_y += tab->m_inc_y,
523
XMoveWindow(m_display, tab->m_tabwin, pos_x, pos_y);
525
//dont move FluxboxWindow if the iterator = this
527
tab->m_win->configure(m_win->getXFrame(), m_win->getYFrame(),
528
m_win->getWidth(), m_win->getHeight());
532
m_stoptabs = false;//thaw tablist
535
//------------- calcIncrease ----------------
536
// calculates m_inc_x and m_inc_y for tabs
537
// used for positioning the tabs.
538
//-------------------------------------------
539
void Tab::calcIncrease(void) {
541
cerr << "Calculating tab increase" << endl;
545
int inc_x = 0, inc_y = 0;
546
unsigned int i = 0, tabs = numObjects();
548
if (m_win->getScreen()->getTabPlacement() == PTOP ||
549
m_win->getScreen()->getTabPlacement() == PBOTTOM ||
553
switch(m_win->getScreen()->getTabAlignment()) {
564
inc_x = calcRelativeWidth();
569
} else if (m_win->getScreen()->getTabPlacement() == PLEFT ||
570
m_win->getScreen()->getTabPlacement() == PRIGHT) {
573
switch(m_win->getScreen()->getTabAlignment()) {
584
inc_y = calcRelativeHeight();
591
for (tab = getFirst(this); tab!=0; tab = tab->m_next, i++) {
593
//TODO: move this out from here?
594
if ((m_win->getScreen()->getTabPlacement() == PTOP ||
595
m_win->getScreen()->getTabPlacement() == PBOTTOM ||
596
m_win->isShaded()) &&
597
m_win->getScreen()->getTabAlignment() == ARELATIVE) {
598
if (!((m_win->getWidth() +
599
m_win->getScreen()->getBorderWidth2x()) % tabs) ||
600
i >= ((m_win->getWidth() +
601
m_win->getScreen()->getBorderWidth2x()) % tabs)) {
602
tab->setTabWidth(inc_x);
603
tab->m_inc_x = inc_x;
604
} else { // adding 1 extra pixel to get tabs like win width
605
tab->setTabWidth(inc_x + 1);
606
tab->m_inc_x = inc_x + 1;
608
tab->m_inc_y = inc_y;
609
} else if (m_win->getScreen()->getTabAlignment() == ARELATIVE) {
610
if (!((m_win->getHeight() +
611
m_win->getScreen()->getBorderWidth2x()) % tabs) ||
612
i >= ((m_win->getHeight() +
613
m_win->getScreen()->getBorderWidth2x()) % tabs)) {
615
tab->setTabHeight(inc_y);
616
tab->m_inc_y = inc_y;
618
// adding 1 extra pixel to get tabs match window width
619
tab->setTabHeight(inc_y + 1);
620
tab->m_inc_y = inc_y + 1;
622
tab->m_inc_x = inc_x;
623
} else { // non relative modes
624
tab->m_inc_x = inc_x;
625
tab->m_inc_y = inc_y;
630
//------------- buttonPressEvent -----------
631
// Handle button press event here.
632
//------------------------------------------
633
void Tab::buttonPressEvent(XButtonEvent *be) {
634
//draw in pressed mode
637
//set window to titlewindow so we can take advatage of drag function
638
be->window = m_win->frame.title;
640
//call windows buttonpress eventhandler
641
m_win->buttonPressEvent(be);
644
//----------- buttonReleaseEvent ----------
645
// Handle button release event here.
646
// If tab is dropped then it should try to find
647
// the window where the tab where dropped.
648
//-----------------------------------------
649
void Tab::buttonReleaseEvent(XButtonEvent *be) {
655
//erase tabmoving rectangle
656
XDrawRectangle(m_display, m_win->getScreen()->getRootWindow(),
657
m_win->getScreen()->getOpGC(),
661
Fluxbox::instance()->ungrab();
662
XUngrabPointer(m_display, CurrentTime);
664
//storage of window and pos of window where we dropped the tab
666
int dest_x = 0, dest_y = 0;
668
//find window on coordinates of buttonReleaseEvent
669
if (XTranslateCoordinates(m_display, m_win->getScreen()->getRootWindow(),
670
m_win->getScreen()->getRootWindow(),
671
be->x_root, be->y_root, &dest_x, &dest_y, &child)) {
673
Tab *tab = Fluxbox::instance()->searchTab(child);
674
FluxboxWindow *win = Fluxbox::instance()->searchWindow(child);
675
//search tablist for a tabwindow
676
if ( (tab!=0) || (m_win->getScreen()->isSloppyWindowGrouping() &&
677
(win!=0) && (tab = win->getTab())!=0)) {
679
if (tab == this) // inserting ourself to ourself causes a disconnect
682
// do only attach a hole chain if we dropped the
683
// first tab in the dropped chain...
687
// attach this tabwindow chain to the tabwindow chain we found.
694
unsigned int placement = m_win->getScreen()->getTabPlacement();
696
// (ab)using dest_x and dest_y
700
if (placement == PTOP || placement == PBOTTOM || m_win->isShaded()) {
701
if (placement == PBOTTOM && !m_win->isShaded())
702
dest_y -= m_win->getHeight();
703
else if (placement != PTOP && m_win->isShaded())
704
dest_y -= m_win->getTitleHeight();
706
dest_y += m_win->getTitleHeight();
708
switch(m_win->getScreen()->getTabAlignment()) {
710
dest_x -= (m_win->getWidth() / 2) - (m_size_w / 2);
713
dest_x -= m_win->getWidth() - m_size_w;
719
} else { // PLEFT & PRIGHT
720
if (placement == PRIGHT)
721
dest_x = be->x_root - m_win->getWidth();
723
switch(m_win->getScreen()->getTabAlignment()) {
725
dest_y -= (m_win->getHeight() / 2) - (m_size_h / 2);
728
dest_y -= m_win->getHeight() - m_size_h;
734
//TODO: this causes an calculate increase event, even if we
735
// only are moving a window
736
m_win->configure(dest_x, dest_y, m_win->getWidth(), m_win->getHeight());
741
//raise this tabwindow
744
//set window to title window soo we can use m_win handler for menu
745
be->window = m_win->frame.title;
747
//call windows buttonrelease event handler so it can popup a menu if needed
748
m_win->buttonReleaseEvent(be);
753
//------------- exposeEvent ------------
754
// Handle expose event here.
755
// Draws the tab unpressed
756
//--------------------------------------
757
void Tab::exposeEvent(XExposeEvent *ee) {
761
//----------- motionNotifyEvent --------
762
// Handles motion event here
763
// Draws the rectangle of moving tab
764
//--------------------------------------
765
void Tab::motionNotifyEvent(XMotionEvent *me) {
767
Fluxbox *fluxbox = Fluxbox::instance();
769
//if mousebutton 2 is pressed
770
if (me->state & Button2Mask) {
774
XGrabPointer(m_display, me->window, False, Button2MotionMask |
775
ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
776
None, fluxbox->getMoveCursor(), CurrentTime);
780
m_move_x = me->x_root - 1;
781
m_move_y = me->y_root - 1;
783
XDrawRectangle(m_display, m_win->getScreen()->getRootWindow(),
784
m_win->getScreen()->getOpGC(),
790
int dx = me->x_root - 1, dy = me->y_root - 1;
792
dx -= m_win->getScreen()->getBorderWidth();
793
dy -= m_win->getScreen()->getBorderWidth();
795
if (m_win->getScreen()->getEdgeSnapThreshold()) {
796
int drx = m_win->getScreen()->getWidth() - (dx + 1);
798
if (dx > 0 && dx < drx && dx < m_win->getScreen()->getEdgeSnapThreshold())
800
else if (drx > 0 && drx < m_win->getScreen()->getEdgeSnapThreshold())
801
dx = m_win->getScreen()->getWidth() - 1;
803
int dtty, dbby, dty, dby;
805
switch (m_win->getScreen()->getToolbarPlacement()) {
806
case Toolbar::TOPLEFT:
807
case Toolbar::TOPCENTER:
808
case Toolbar::TOPRIGHT:
809
dtty = m_win->getScreen()->getToolbar()->getExposedHeight() +
810
m_win->getScreen()->getBorderWidth();
811
dbby = m_win->getScreen()->getHeight();
816
dbby = m_win->getScreen()->getToolbar()->getY();
821
dby = dbby - (dy + 1);
823
if (dy > 0 && dty < m_win->getScreen()->getEdgeSnapThreshold())
825
else if (dby > 0 && dby < m_win->getScreen()->getEdgeSnapThreshold())
831
XDrawRectangle(m_display, m_win->getScreen()->getRootWindow(),
832
m_win->getScreen()->getOpGC(),
836
//redraw rectangle at new pos
839
XDrawRectangle(m_display, m_win->getScreen()->getRootWindow(),
840
m_win->getScreen()->getOpGC(),
848
//-------------- getFirst() ---------
849
// Returns the first Tab in the chain
851
//-----------------------------------
852
Tab *Tab::getFirst(Tab *current) {
858
for (; i->m_prev != 0; i = i->m_prev);
862
//-------------- getLast() ---------
863
// Returns the last Tab in the chain
865
//-----------------------------------
866
Tab *Tab::getLast(Tab *current) {
871
for (; i->m_next != 0; i = i->m_next);
875
//-------------- insert ------------
877
// Inserts a tab in the chain
878
//----------------------------------
879
void Tab::insert(Tab *tab) {
881
if (!tab || tab == this) //dont insert if the tab = 0 or the tab = this
884
Tab *first = getFirst(this);
886
//if the tab already in chain then disconnect it
887
for (; first!=0; first = first->m_next) {
890
cerr<<"Tab already in chain. Disconnecting!"<<endl;
897
//get last tab in the chain to be inserted
899
for (; last->m_next!=0; last=last->m_next);
900
//do sticky before we connect it to the chain
901
//sticky bit on window
902
if (m_win->isStuck() && !tab->m_win->isStuck() ||
903
!m_win->isStuck() && tab->m_win->isStuck())
904
tab->m_win->stick(); //this will set all the m_wins in the list
906
//connect the tab to this chain
909
m_next->m_prev = last;
911
last->m_next = m_next;
915
bool resize_tabs = false;
917
//TODO: cleanup and optimize
918
//move and resize all windows in the tablist we inserted
919
//only from first tab of the inserted chain to the last
920
for (; tab!=last->m_next; tab=tab->m_next) {
921
if (m_win->isShaded() != tab->m_win->isShaded()) {
922
tab->m_stoptabs = true; // we don't want any actions performed on the
923
// tabs, just the tab windows!
924
if (m_win->getScreen()->getTabPlacement() == PLEFT ||
925
m_win->getScreen()->getTabPlacement() == PRIGHT)
928
// if the window we are grouping to, we need to shade the tab window
929
// _after_ reconfigure
930
if(m_win->isShaded()) {
931
tab->m_win->configure(m_win->getXFrame(), m_win->getYFrame(),
932
m_win->getWidth(), m_win->getHeight());
935
tab->m_win->shade(); // switch to correct shade state
936
tab->m_win->configure(m_win->getXFrame(), m_win->getYFrame(),
937
m_win->getWidth(), m_win->getHeight());
940
tab->m_stoptabs = false;
942
// both window have the same shaded state and have different sizes,
943
// checking this so that I'll only do shade on windows if configure did
945
} else if ((m_win->getWidth() != tab->m_win->getWidth()) ||
946
(m_win->getHeight() != tab->m_win->getHeight())) {
948
tab->m_win->configure(m_win->getXFrame(), m_win->getYFrame(),
949
m_win->getWidth(), m_win->getHeight());
951
// need to shade the tab window as configure will mess it up
952
if (m_win->isShaded())
957
// resize if in relative mode or resize_tabs is true
958
if(m_win->getScreen()->getTabAlignment() == ARELATIVE ||
967
//---------- disconnect() --------------
968
// Disconnects the tab from any chain
969
//--------------------------------------
970
void Tab::disconnect() {
972
if (m_prev) { //if this have a chain to "the left" (previous tab) then set it's next to this next
973
m_prev->m_next = m_next;
976
if (m_next) { //if this have a chain to "the right" (next tab) then set it's prev to this prev
977
m_next->m_prev = m_prev;
981
//mark as no chain, previous and next.
985
//reposition the tabs
987
if (m_win->getScreen()->getTabAlignment() == ARELATIVE)
992
if (m_win->getScreen()->getTabAlignment() == ARELATIVE)
998
// ------------ setTabWidth --------------
999
// Sets Tab width _including_ borders
1000
// ---------------------------------------
1001
void Tab::setTabWidth(unsigned int w) {
1002
if (w > m_win->getScreen()->getWindowStyle()->tab.border_width_2x &&
1005
XResizeWindow(m_display, m_tabwin,
1006
m_size_w - m_win->getScreen()->getWindowStyle()->tab.border_width_2x,
1007
m_size_h - m_win->getScreen()->getWindowStyle()->tab.border_width_2x);
1009
loadTheme(); // rerender themes to right size
1010
focus(); // redraw the window
1014
// ------------ setTabHeight ---------
1015
// Sets Tab height _including_ borders
1016
// ---------------------------------------
1017
void Tab::setTabHeight(unsigned int h) {
1018
if (h > m_win->getScreen()->getWindowStyle()->tab.border_width_2x &&
1021
XResizeWindow(m_display, m_tabwin,
1022
m_size_w - m_win->getScreen()->getWindowStyle()->tab.border_width_2x,
1023
m_size_h - m_win->getScreen()->getWindowStyle()->tab.border_width_2x);
1025
loadTheme(); // rerender themes to right size
1026
focus(); // redraw the window
1030
// ------------ resizeGroup --------------
1031
// This function is used when (un)shading
1032
// to get right size/width of tabs when
1033
// PLeft || PRight && isTabRotateVertical
1034
// ---------------------------------------
1035
void Tab::resizeGroup(void) {
1037
cerr <<__FILE__<<"("<<__LINE__<<"): Resizing group"<<endl;
1040
for (first = getFirst(this); first != 0; first = first->m_next) {
1041
if ((m_win->getScreen()->getTabPlacement() == PLEFT ||
1042
m_win->getScreen()->getTabPlacement() == PRIGHT) &&
1043
m_win->getScreen()->isTabRotateVertical() &&
1044
!m_win->isShaded()) {
1045
first->setTabWidth(m_win->getScreen()->getTabHeight());
1046
first->setTabHeight(m_win->getScreen()->getTabWidth());
1048
first->setTabWidth(m_win->getScreen()->getTabWidth());
1049
first->setTabHeight(m_win->getScreen()->getTabHeight());
1051
//TODO: do I have to set this all the time?
1052
first->m_configured = true; //used in Fluxbox::reconfigure()
1056
//------------- calcRelativeWidth --------
1057
// Returns: Calculated width for relative
1059
//----------------------------------------
1060
unsigned int Tab::calcRelativeWidth() {
1062
//calculate num objs in list (extract this to a function?)
1063
for (Tab *first=getFirst(this); first!=0; first=first->m_next, num++);
1065
return ((m_win->getWidth() + m_win->getScreen()->getBorderWidth2x())/num);
1068
//--------------- numObjects -------------------
1069
// Returns the number of objects in
1071
//-----------------------------------------------
1072
unsigned int Tab::numObjects() {
1073
unsigned int num = 0;
1074
for (Tab *tab = getFirst(this); tab != 0; tab = tab->m_next, num++);
1078
//------------- calcRelativeHeight -------
1079
// Returns: Calculated height for relative
1081
//----------------------------------------
1082
unsigned int Tab::calcRelativeHeight() {
1083
return ((m_win->getHeight() +
1084
m_win->getScreen()->getBorderWidth2x())/numObjects());
1087
//------------- calcCenterXPos -----------
1088
// Returns: Calculated x position for
1089
// centered alignment
1090
//----------------------------------------
1091
unsigned int Tab::calcCenterXPos() {
1092
return (m_win->getXFrame() + ((m_win->getWidth() -
1093
(m_size_w * numObjects())) / 2));
1096
//------------- calcCenterYPos -----------
1097
// Returns: Calculated y position for
1098
// centered alignment
1099
//----------------------------------------
1100
unsigned int Tab::calcCenterYPos() {
1101
return (m_win->getYFrame() + ((m_win->getHeight() -
1102
(m_size_h * numObjects())) / 2));
1106
//------- getTabPlacementString ----------
1107
// Returns the tabplacement string of the
1108
// tabplacement number on success else 0.
1109
//----------------------------------------
1110
const char *Tab::getTabPlacementString(Tab::Placement placement) {
1111
for (int i=0; i<(PNONE / 5); i++) {
1112
if (m_tabplacementlist[i] == placement)
1113
return m_tabplacementlist[i].string;
1118
//------- getTabPlacementNum -------------
1119
// Returns the tabplacement number of the
1120
// tabplacement string on success else
1121
// the type none on failure.
1122
//----------------------------------------
1123
Tab::Placement Tab::getTabPlacementNum(const char *string) {
1124
for (int i=0; i<(PNONE / 5); i ++) {
1125
if (m_tabplacementlist[i] == string) {
1126
return static_cast<Tab::Placement>(m_tabplacementlist[i].tp);
1132
//------- getTabAlignmentString ----------
1133
// Returns the tabplacement string of the
1134
// tabplacement number on success else 0.
1135
//----------------------------------------
1136
const char *Tab::getTabAlignmentString(Tab::Alignment alignment) {
1137
for (int i=0; i<ANONE; i++) {
1138
if (m_tabalignmentlist[i] == alignment)
1139
return m_tabalignmentlist[i].string;
1144
//------- getTabAlignmentNum -------------
1145
// Returns the tabplacement number of the
1146
// tabplacement string on success else
1147
// the type none on failure.
1148
//----------------------------------------
1149
Tab::Alignment Tab::getTabAlignmentNum(const char *string) {
1150
for (int i=0; i<ANONE; i++) {
1151
if (m_tabalignmentlist[i] == string) {
1152
return static_cast<Tab::Alignment>(m_tabalignmentlist[i].tp);