diff options
-rw-r--r-- | generic/tkBind.c | 25 | ||||
-rw-r--r-- | generic/ttk/ttkNotebook.c | 81 |
2 files changed, 68 insertions, 38 deletions
diff --git a/generic/tkBind.c b/generic/tkBind.c index 567c51f..61b44df 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -3466,12 +3466,28 @@ HandleEventGenerate( if ((warp != 0) && Tk_IsMapped(tkwin)) { TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display); + /* + * TODO: No protection is in place to handle dispPtr destruction + * before DoWarp is called back. + */ + + Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display, + event.general.xmotion.window); + if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) { Tcl_DoWhenIdle(DoWarp, dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = Tk_IdToWindow(dispPtr->display, - event.general.xmotion.window); + + if (warpWindow != dispPtr->warpWindow) { + if (warpWindow) { + Tcl_Preserve(warpWindow); + } + if (dispPtr->warpWindow) { + Tcl_Release(dispPtr->warpWindow); + } + dispPtr->warpWindow = warpWindow; + } dispPtr->warpMainwin = mainWin; dispPtr->warpX = event.general.xmotion.x; dispPtr->warpY = event.general.xmotion.y; @@ -3559,6 +3575,11 @@ DoWarp( TkpWarpPointer(dispPtr); XForceScreenSaver(dispPtr->display, ScreenSaverReset); } + + if (dispPtr->warpWindow) { + Tcl_Release(dispPtr->warpWindow); + dispPtr->warpWindow = None; + } dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c index 81a8b64..06aa275 100644 --- a/generic/ttk/ttkNotebook.c +++ b/generic/ttk/ttkNotebook.c @@ -4,6 +4,7 @@ #include <string.h> #include <ctype.h> +#include <math.h> #include <stdio.h> #include <tk.h> @@ -288,13 +289,14 @@ static void ActivateTab(Notebook *nb, int index) * TabState -- * Return the state of the specified tab, based on * notebook state, currentIndex, activeIndex, and user-specified tab state. - * The USER1 bit is set for the leftmost tab, and USER2 - * is set for the rightmost tab. + * The USER1 bit is set for the leftmost visible tab, and USER2 + * is set for the rightmost visible tab. */ static Ttk_State TabState(Notebook *nb, int index) { Ttk_State state = nb->core.state; Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index); + int i = 0; if (index == nb->notebook.currentIndex) { state |= TTK_STATE_SELECTED; @@ -305,11 +307,25 @@ static Ttk_State TabState(Notebook *nb, int index) if (index == nb->notebook.activeIndex) { state |= TTK_STATE_ACTIVE; } - if (index == 0) { - state |= TTK_STATE_USER1; + for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + if (tab->state == TAB_STATE_HIDDEN) { + continue; + } + if (index == i) { + state |= TTK_STATE_USER1; + } + break; } - if (index == Ttk_NumberSlaves(nb->notebook.mgr) - 1) { - state |= TTK_STATE_USER2; + for (i = Ttk_NumberSlaves(nb->notebook.mgr) - 1; i >= 0; --i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + if (tab->state == TAB_STATE_HIDDEN) { + continue; + } + if (index == i) { + state |= TTK_STATE_USER2; + } + break; } if (tab->state == TAB_STATE_DISABLED) { state |= TTK_STATE_DISABLED; @@ -325,6 +341,8 @@ static Ttk_State TabState(Notebook *nb, int index) /* TabrowSize -- * Compute max height and total width of all tabs (horizontal layouts) * or total height and max width (vertical layouts). + * The -mintabwidth style option is taken into account (for the width + * only). * * Side effects: * Sets width and height fields for all tabs. @@ -334,7 +352,7 @@ static Ttk_State TabState(Notebook *nb, int index) * (max height/width) but not parallel (total width/height). */ static void TabrowSize( - Notebook *nb, Ttk_Orient orient, int *widthPtr, int *heightPtr) + Notebook *nb, Ttk_Orient orient, int minTabWidth, int *widthPtr, int *heightPtr) { Ttk_Layout tabLayout = nb->notebook.tabLayout; int tabrowWidth = 0, tabrowHeight = 0; @@ -346,6 +364,7 @@ static void TabrowSize( Ttk_RebindSublayout(tabLayout, tab); Ttk_LayoutSize(tabLayout,tabState,&tab->width,&tab->height); + tab->width = MAX(tab->width, minTabWidth); if (orient == TTK_ORIENT_HORIZONTAL) { tabrowHeight = MAX(tabrowHeight, tab->height); @@ -406,7 +425,7 @@ static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr) /* Tab row: */ - TabrowSize(nb, nbstyle.tabOrient, &tabrowWidth, &tabrowHeight); + TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight); tabrowHeight += Ttk_PaddingHeight(nbstyle.tabMargins); tabrowWidth += Ttk_PaddingWidth(nbstyle.tabMargins); @@ -436,47 +455,32 @@ static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr) /* SqueezeTabs -- * Squeeze or stretch tabs to fit within the tab area parcel. + * This happens independently of the -mintabwidth style option. * - * All tabs are adjusted by an equal amount, but will not be made - * smaller than the minimum width. (If all the tabs still do - * not fit in the available space, the rightmost ones will - * be further squozen by PlaceTabs()). - * - * The algorithm does not always yield an optimal layout, but does - * have the important property that decreasing the available width - * by one pixel will cause at most one tab to shrink by one pixel; - * this means that tabs resize "smoothly" when the window shrinks - * and grows. + * All tabs are adjusted by an equal amount. * * @@@ <<NOTE-TABPOSITION>> bug: only works for horizontal orientations * @@@ <<NOTE-SQUEEZE-HIDDEN>> does not account for hidden tabs. */ static void SqueezeTabs( - Notebook *nb, int needed, int available, int minTabWidth) + Notebook *nb, int needed, int available) { int nTabs = Ttk_NumberSlaves(nb->notebook.mgr); if (nTabs > 0) { - int difference = available - needed, - delta = difference / nTabs, - remainder = difference % nTabs, - slack = 0; + int difference = available - needed; + double fraction = (double)difference / needed; + double slack = 0; + double ad; int i; - if (remainder < 0) { remainder += nTabs; --delta; } - for (i = 0; i < nTabs; ++i) { Tab *tab = Ttk_SlaveData(nb->notebook.mgr,i); - int adj = delta + (i < remainder) + slack; - - if (tab->width + adj >= minTabWidth) { - tab->width += adj; - slack = 0; - } else { - slack = adj - (minTabWidth - tab->width); - tab->width = minTabWidth; - } + + ad = slack + tab->width * fraction; + tab->width += (int)ad; + slack = ad - floor(ad); } } } @@ -539,8 +543,13 @@ static void NotebookDoLayout(void *recordPtr) Ttk_PlaceLayout(nb->core.layout, nb->core.state, Ttk_WinBox(nbwin)); /* Place tabs: + * Note: TabrowSize() takes into account -mintabwidth, but the tabs will + * actually have this minimum size when displayed only if there is enough + * space to draw the tabs with this width. Otherwise some of the tabs can + * be squeezed to a size smaller than -mintabwidth because we prefer + * displaying all tabs than than honoring -mintabwidth for all of them. */ - TabrowSize(nb, nbstyle.tabOrient, &tabrowWidth, &tabrowHeight); + TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight); tabrowBox = Ttk_PadBox( Ttk_PositionBox(&cavity, tabrowWidth + Ttk_PaddingWidth(nbstyle.tabMargins), @@ -548,7 +557,7 @@ static void NotebookDoLayout(void *recordPtr) nbstyle.tabPosition), nbstyle.tabMargins); - SqueezeTabs(nb, tabrowWidth, tabrowBox.width, nbstyle.minTabWidth); + SqueezeTabs(nb, tabrowWidth, tabrowBox.width); PlaceTabs(nb, tabrowBox, nbstyle.tabPlacement); /* Layout for client area frame: |