aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfluxgen <fluxgen>2002-08-02 12:58:37 (GMT)
committerfluxgen <fluxgen>2002-08-02 12:58:37 (GMT)
commitc28bd74febd7587a2ab10c5b1b6554f6ed8a5ff3 (patch)
treec095c7cf37af19f6b3d602a43a27f8e977792e0b /src
parent378c946d89569afcfe61fcafcf90fa0247673da9 (diff)
downloadfluxbox_paul-c28bd74febd7587a2ab10c5b1b6554f6ed8a5ff3.zip
fluxbox_paul-c28bd74febd7587a2ab10c5b1b6554f6ed8a5ff3.tar.bz2
added autogrouping-from-tab patch from Steve Cooper
Diffstat (limited to 'src')
-rw-r--r--src/Basemenu.hh4
-rw-r--r--src/Rootmenu.cc27
-rw-r--r--src/Rootmenu.hh6
-rw-r--r--src/Screen.cc41
-rw-r--r--src/Screen.hh7
-rw-r--r--src/Tab.cc38
-rw-r--r--src/Tab.hh9
-rw-r--r--src/Window.cc17
8 files changed, 119 insertions, 30 deletions
diff --git a/src/Basemenu.hh b/src/Basemenu.hh
index 137eb8e..4e48f4c 100644
--- a/src/Basemenu.hh
+++ b/src/Basemenu.hh
@@ -22,7 +22,7 @@
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23// DEALINGS IN THE SOFTWARE. 23// DEALINGS IN THE SOFTWARE.
24 24
25// $Id: Basemenu.hh,v 1.14 2002/05/19 12:57:47 fluxgen Exp $ 25// $Id: Basemenu.hh,v 1.15 2002/08/02 12:52:44 fluxgen Exp $
26 26
27#ifndef BASEMENU_HH 27#ifndef BASEMENU_HH
28#define BASEMENU_HH 28#define BASEMENU_HH
@@ -126,6 +126,8 @@ protected:
126 int x= -1, int y= -1, unsigned int width= 0, unsigned int height= 0); 126 int x= -1, int y= -1, unsigned int width= 0, unsigned int height= 0);
127 virtual void redrawTitle(); 127 virtual void redrawTitle();
128 virtual void internal_hide(); 128 virtual void internal_hide();
129 inline Basemenu *GetParent() { return m_parent; }
130 inline const Basemenu *GetParent() const { return m_parent; }
129}; 131};
130 132
131class BasemenuItem { 133class BasemenuItem {
diff --git a/src/Rootmenu.cc b/src/Rootmenu.cc
index 5339630..66df012 100644
--- a/src/Rootmenu.cc
+++ b/src/Rootmenu.cc
@@ -50,7 +50,10 @@
50#endif // MAXPATHLEN 50#endif // MAXPATHLEN
51 51
52 52
53Rootmenu::Rootmenu(BScreen *scrn) : Basemenu(scrn) { 53Rootmenu::Rootmenu(BScreen *scrn)
54: Basemenu(scrn),
55 auto_group_window(0)
56{
54 screen = scrn; 57 screen = scrn;
55} 58}
56 59
@@ -73,7 +76,10 @@ void Rootmenu::itemSelected(int button, unsigned int index) {
73 sprintf(displaystring + strlen(displaystring) - 1, "%d", 76 sprintf(displaystring + strlen(displaystring) - 1, "%d",
74 screen->getScreenNumber()); 77 screen->getScreenNumber());
75 78
79 screen->setAutoGroupWindow(useAutoGroupWindow());
80
76 bexec(item->exec().c_str(), displaystring); 81 bexec(item->exec().c_str(), displaystring);
82
77 #else // __EMX__ 83 #else // __EMX__
78 spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", item->exec().c_str(), NULL); 84 spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", item->exec().c_str(), NULL);
79 #endif // !__EMX__ 85 #endif // !__EMX__
@@ -113,3 +119,22 @@ void Rootmenu::itemSelected(int button, unsigned int index) {
113 } 119 }
114} 120}
115 121
122void Rootmenu::setAutoGroupWindow(Window window)
123{
124 auto_group_window = window;
125}
126
127Window Rootmenu::useAutoGroupWindow()
128{
129 // Return and clear the auto-grouping state.
130 Window w = auto_group_window;
131 if (w)
132 auto_group_window = 0; // clear it immediately
133 // If not set check the parent and the parent's parent, ...
134 else {
135 Rootmenu* parent = dynamic_cast<Rootmenu*>(GetParent());
136 if (parent)
137 w = parent->useAutoGroupWindow();
138 }
139 return w;
140}
diff --git a/src/Rootmenu.hh b/src/Rootmenu.hh
index d8b7d95..16efb62 100644
--- a/src/Rootmenu.hh
+++ b/src/Rootmenu.hh
@@ -32,6 +32,7 @@ class BScreen;
32class Rootmenu : public Basemenu { 32class Rootmenu : public Basemenu {
33private: 33private:
34 BScreen *screen; 34 BScreen *screen;
35 Window auto_group_window;
35 36
36 37
37protected: 38protected:
@@ -40,6 +41,11 @@ protected:
40 41
41public: 42public:
42 Rootmenu(BScreen *); 43 Rootmenu(BScreen *);
44 void setAutoGroupWindow(Window window);
45
46
47private:
48 Window useAutoGroupWindow();
43}; 49};
44 50
45 51
diff --git a/src/Screen.cc b/src/Screen.cc
index 6a2485e..cdc6bcd 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -22,7 +22,7 @@
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23// DEALINGS IN THE SOFTWARE. 23// DEALINGS IN THE SOFTWARE.
24 24
25// $Id: Screen.cc,v 1.58 2002/07/23 17:11:59 fluxgen Exp $ 25// $Id: Screen.cc,v 1.59 2002/08/02 12:52:44 fluxgen Exp $
26 26
27//use GNU extensions 27//use GNU extensions
28#ifndef _GNU_SOURCE 28#ifndef _GNU_SOURCE
@@ -474,7 +474,7 @@ namespace {
474 } 474 }
475} 475}
476 476
477BScreen::~BScreen(void) { 477BScreen::~BScreen() {
478 #ifdef GNOME 478 #ifdef GNOME
479 XDestroyWindow(getBaseDisplay()->getXDisplay(), gnome_win); 479 XDestroyWindow(getBaseDisplay()->getXDisplay(), gnome_win);
480 #endif 480 #endif
@@ -548,7 +548,7 @@ BScreen::~BScreen(void) {
548 548
549} 549}
550 550
551void BScreen::reconfigure(void) { 551void BScreen::reconfigure() {
552 #ifdef DEBUG 552 #ifdef DEBUG
553 cerr<<__FILE__<<"("<<__LINE__<<"): BScreen::reconfigure"<<endl; 553 cerr<<__FILE__<<"("<<__LINE__<<"): BScreen::reconfigure"<<endl;
554 #endif 554 #endif
@@ -653,7 +653,7 @@ void BScreen::reconfigure(void) {
653} 653}
654 654
655 655
656void BScreen::rereadMenu(void) { 656void BScreen::rereadMenu() {
657 initMenu(); 657 initMenu();
658 raiseWindows(0, 0); 658 raiseWindows(0, 0);
659 659
@@ -661,11 +661,11 @@ void BScreen::rereadMenu(void) {
661} 661}
662 662
663 663
664void BScreen::removeWorkspaceNames(void) { 664void BScreen::removeWorkspaceNames() {
665 workspaceNames.erase(workspaceNames.begin(), workspaceNames.end()); 665 workspaceNames.erase(workspaceNames.begin(), workspaceNames.end());
666} 666}
667 667
668void BScreen::updateWorkspaceNamesAtom(void) { 668void BScreen::updateWorkspaceNamesAtom() {
669 669
670#ifdef GNOME 670#ifdef GNOME
671 XTextProperty text; 671 XTextProperty text;
@@ -741,7 +741,7 @@ FluxboxWindow *BScreen::getIcon(unsigned int index) {
741} 741}
742 742
743 743
744int BScreen::addWorkspace(void) { 744int BScreen::addWorkspace() {
745 Workspace *wkspc = new Workspace(this, workspacesList.size()); 745 Workspace *wkspc = new Workspace(this, workspacesList.size());
746 workspacesList.push_back(wkspc); 746 workspacesList.push_back(wkspc);
747 //add workspace to workspacemenu 747 //add workspace to workspacemenu
@@ -760,7 +760,7 @@ int BScreen::addWorkspace(void) {
760} 760}
761 761
762 762
763int BScreen::removeLastWorkspace(void) { 763int BScreen::removeLastWorkspace() {
764 if (workspacesList.size() > 1) { 764 if (workspacesList.size() > 1) {
765 Workspace *wkspc = workspacesList.back(); 765 Workspace *wkspc = workspacesList.back();
766 766
@@ -888,7 +888,7 @@ void BScreen::removeNetizen(Window w) {
888} 888}
889 889
890 890
891void BScreen::updateNetizenCurrentWorkspace(void) { 891void BScreen::updateNetizenCurrentWorkspace() {
892 #ifdef NEWWMSPEC 892 #ifdef NEWWMSPEC
893 //update _NET_WM_CURRENT_DESKTOP 893 //update _NET_WM_CURRENT_DESKTOP
894 int workspace = getCurrentWorkspaceID(); 894 int workspace = getCurrentWorkspaceID();
@@ -914,7 +914,7 @@ void BScreen::updateNetizenCurrentWorkspace(void) {
914} 914}
915 915
916 916
917void BScreen::updateNetizenWorkspaceCount(void) { 917void BScreen::updateNetizenWorkspaceCount() {
918 918
919 Netizens::iterator it = netizenList.begin(); 919 Netizens::iterator it = netizenList.begin();
920 Netizens::iterator it_end = netizenList.end(); 920 Netizens::iterator it_end = netizenList.end();
@@ -941,7 +941,7 @@ void BScreen::updateNetizenWorkspaceCount(void) {
941} 941}
942 942
943 943
944void BScreen::updateNetizenWindowFocus(void) { 944void BScreen::updateNetizenWindowFocus() {
945 945
946 Netizens::iterator it = netizenList.begin(); 946 Netizens::iterator it = netizenList.begin();
947 Netizens::iterator it_end = netizenList.end(); 947 Netizens::iterator it_end = netizenList.end();
@@ -1194,7 +1194,7 @@ void BScreen::prevFocus(int opts) {
1194//--------- raiseFocus ----------- 1194//--------- raiseFocus -----------
1195// Raise the current focused window 1195// Raise the current focused window
1196//-------------------------------- 1196//--------------------------------
1197void BScreen::raiseFocus(void) { 1197void BScreen::raiseFocus() {
1198 bool have_focused = false; 1198 bool have_focused = false;
1199 int focused_window_number = -1; 1199 int focused_window_number = -1;
1200 1200
@@ -1210,7 +1210,7 @@ void BScreen::raiseFocus(void) {
1210 raiseWindow(fluxbox->getFocusedWindow()); 1210 raiseWindow(fluxbox->getFocusedWindow());
1211} 1211}
1212 1212
1213void BScreen::initMenu(void) { 1213void BScreen::initMenu() {
1214 I18n *i18n = I18n::instance(); 1214 I18n *i18n = I18n::instance();
1215 1215
1216 if (rootmenu) { 1216 if (rootmenu) {
@@ -1571,7 +1571,7 @@ void BScreen::createStyleMenu(Rootmenu *menu, bool newmenu, const char *label, c
1571 1571
1572} 1572}
1573 1573
1574void BScreen::shutdown(void) { 1574void BScreen::shutdown() {
1575 fluxbox->grab(); 1575 fluxbox->grab();
1576 1576
1577 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), NoEventMask); 1577 XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), NoEventMask);
@@ -1688,7 +1688,7 @@ void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
1688} 1688}
1689 1689
1690 1690
1691void BScreen::hideGeometry(void) { 1691void BScreen::hideGeometry() {
1692 if (geom_visible) { 1692 if (geom_visible) {
1693 XUnmapWindow(getBaseDisplay()->getXDisplay(), geom_window); 1693 XUnmapWindow(getBaseDisplay()->getXDisplay(), geom_window);
1694 geom_visible = false; 1694 geom_visible = false;
@@ -1735,8 +1735,17 @@ bool BScreen::doSkipWindow(const FluxboxWindow *w, int opts) {
1735 (opts & CYCLESKIPSHADED) != 0 && w->isShaded()); // skip if shaded 1735 (opts & CYCLESKIPSHADED) != 0 && w->isShaded()); // skip if shaded
1736} 1736}
1737 1737
1738//----------- useAutoGroupWindow -------------
1739// Access and clear the auto-group window
1740//--------------------------------------------
1741FluxboxWindow* BScreen::useAutoGroupWindow() {
1742 Window w = auto_group_window;
1743 auto_group_window = 0;
1744 return w ? Fluxbox::instance()->searchWindow(w) : 0;
1745}
1746
1738#ifdef GNOME 1747#ifdef GNOME
1739void BScreen::initGnomeAtoms(void) { 1748void BScreen::initGnomeAtoms() {
1740 1749
1741 /* create the GNOME window */ 1750 /* create the GNOME window */
1742 gnome_win = XCreateSimpleWindow(getBaseDisplay()->getXDisplay(), 1751 gnome_win = XCreateSimpleWindow(getBaseDisplay()->getXDisplay(),
diff --git a/src/Screen.hh b/src/Screen.hh
index 00d429d..1f4cf89 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -22,7 +22,7 @@
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23// DEALINGS IN THE SOFTWARE. 23// DEALINGS IN THE SOFTWARE.
24 24
25// $Id: Screen.hh,v 1.39 2002/07/23 18:37:05 fluxgen Exp $ 25// $Id: Screen.hh,v 1.40 2002/08/02 12:52:44 fluxgen Exp $
26 26
27#ifndef SCREEN_HH 27#ifndef SCREEN_HH
28#define SCREEN_HH 28#define SCREEN_HH
@@ -181,6 +181,7 @@ public:
181 inline void saveDesktopWheeling(bool s) { resource.desktop_wheeling = s; } 181 inline void saveDesktopWheeling(bool s) { resource.desktop_wheeling = s; }
182 inline void iconUpdate(void) { iconmenu->update(); } 182 inline void iconUpdate(void) { iconmenu->update(); }
183 inline Iconmenu *getIconmenu(void) { return iconmenu; } 183 inline Iconmenu *getIconmenu(void) { return iconmenu; }
184 inline void setAutoGroupWindow(Window w = 0) { auto_group_window = w; }
184 185
185 186
186 #ifdef HAVE_STRFTIME 187 #ifdef HAVE_STRFTIME
@@ -230,6 +231,8 @@ public:
230 void showGeometry(unsigned int, unsigned int); 231 void showGeometry(unsigned int, unsigned int);
231 void hideGeometry(void); 232 void hideGeometry(void);
232 233
234 FluxboxWindow* useAutoGroupWindow(void);
235
233 void updateNetizenCurrentWorkspace(void); 236 void updateNetizenCurrentWorkspace(void);
234 void updateNetizenWorkspaceCount(void); 237 void updateNetizenWorkspaceCount(void);
235 void updateNetizenWindowFocus(void); 238 void updateNetizenWindowFocus(void);
@@ -293,6 +296,8 @@ private:
293 296
294 WorkspaceNames workspaceNames; 297 WorkspaceNames workspaceNames;
295 Workspaces workspacesList; 298 Workspaces workspacesList;
299
300 Window auto_group_window;
296 301
297 struct ScreenResource { 302 struct ScreenResource {
298 ScreenResource(ResourceManager &rm, const std::string &scrname, 303 ScreenResource(ResourceManager &rm, const std::string &scrname,
diff --git a/src/Tab.cc b/src/Tab.cc
index a98aef6..ebe8760 100644
--- a/src/Tab.cc
+++ b/src/Tab.cc
@@ -19,7 +19,7 @@
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE. 20// DEALINGS IN THE SOFTWARE.
21 21
22// $Id: Tab.cc,v 1.29 2002/07/23 17:11:59 fluxgen Exp $ 22// $Id: Tab.cc,v 1.30 2002/08/02 12:57:19 fluxgen Exp $
23 23
24#include "Tab.hh" 24#include "Tab.hh"
25 25
@@ -654,11 +654,25 @@ void Tab::buttonPressEvent(XButtonEvent *be) {
654 //draw in pressed mode 654 //draw in pressed mode
655 draw(true); 655 draw(true);
656 656
657 //set window to titlewindow so we can take advatage of drag function 657 //invoke root menu with auto-glueing?
658 be->window = m_win->frame.title; 658 if (be->button == 3) {
659 BScreen *screen = m_win->getScreen();
660 Rootmenu *rootmenu = screen->getRootmenu();
661 if (! rootmenu->isVisible()) {
662 Fluxbox::instance()->checkMenu();
663 screen->getRootmenu()->move(be->x_root, be->y_root-rootmenu->titleHeight());
664 rootmenu->setAutoGroupWindow(m_win->getClientWindow());
665 rootmenu->show();
666 }
667 }
668 //otherwise let the window handle the event
669 else {
670 //set window to titlewindow so we can take advantage of drag function
671 be->window = m_win->frame.title;
659 672
660 //call windows buttonpress eventhandler 673 //call windows buttonpress eventhandler
661 m_win->buttonPressEvent(be); 674 m_win->buttonPressEvent(be);
675 }
662} 676}
663 677
664//----------- buttonReleaseEvent ---------- 678//----------- buttonReleaseEvent ----------
@@ -1186,3 +1200,17 @@ Tab::Alignment Tab::getTabAlignmentNum(const char *string) {
1186 } 1200 }
1187 return ANONE; 1201 return ANONE;
1188} 1202}
1203
1204//---------- addWindowToGroup ------------
1205// Add a window the the tabbed group
1206//----------------------------------------
1207bool Tab::addWindowToGroup(FluxboxWindow *otherWindow)
1208{
1209 if (!otherWindow || otherWindow == m_win)
1210 return false;
1211 Tab *otherTab = otherWindow->getTab();
1212 if (!otherTab)
1213 return false;
1214 insert(otherTab);
1215 return true;
1216}
diff --git a/src/Tab.hh b/src/Tab.hh
index e3abf51..9c73f20 100644
--- a/src/Tab.hh
+++ b/src/Tab.hh
@@ -19,7 +19,7 @@
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE. 20// DEALINGS IN THE SOFTWARE.
21 21
22// $Id: Tab.hh,v 1.13 2002/05/19 15:35:39 fluxgen Exp $ 22// $Id: Tab.hh,v 1.14 2002/08/02 12:57:19 fluxgen Exp $
23 23
24#ifndef TAB_HH 24#ifndef TAB_HH
25#define TAB_HH 25#define TAB_HH
@@ -81,14 +81,17 @@ public:
81 const Tab *first() const { return getFirst(const_cast<Tab *>(this)); } 81 const Tab *first() const { return getFirst(const_cast<Tab *>(this)); }
82 82
83 const FluxboxWindow *getWindow() const { return m_win; } 83 const FluxboxWindow *getWindow() const { return m_win; }
84 Window getTabWindow() const { return m_tabwin; }
84 unsigned int getTabWidth() const { return m_size_w; } 85 unsigned int getTabWidth() const { return m_size_w; }
85 unsigned int getTabHeight() const { return m_size_h; } 86 unsigned int getTabHeight() const { return m_size_h; }
86 87
87 void resizeGroup(void); // used when (un)shading windows 88 void resizeGroup(); // used when (un)shading windows
88 void calcIncrease(void); 89 void calcIncrease();
89 bool configured() const { return m_configured; } 90 bool configured() const { return m_configured; }
90 void draw(bool pressed) const; 91 void draw(bool pressed) const;
91 92
93 bool addWindowToGroup(FluxboxWindow *window);
94
92 static Tab *getFirst(Tab *current); 95 static Tab *getFirst(Tab *current);
93 static Tab *getLast(Tab *current); 96 static Tab *getLast(Tab *current);
94 97
diff --git a/src/Window.cc b/src/Window.cc
index 9683e5e..85f8d23 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -22,7 +22,7 @@
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23// DEALINGS IN THE SOFTWARE. 23// DEALINGS IN THE SOFTWARE.
24 24
25// $Id: Window.cc,v 1.63 2002/07/23 17:11:59 fluxgen Exp $ 25// $Id: Window.cc,v 1.64 2002/08/02 12:58:37 fluxgen Exp $
26 26
27#include "Window.hh" 27#include "Window.hh"
28 28
@@ -758,7 +758,7 @@ void FluxboxWindow::grabButtons() {
758 frame.plate, True, ButtonPressMask, 758 frame.plate, True, ButtonPressMask,
759 GrabModeSync, GrabModeSync, None, None); 759 GrabModeSync, GrabModeSync, None, None);
760 XUngrabButton(display, Button1, Mod1Mask|Mod2Mask|Mod3Mask, frame.plate); 760 XUngrabButton(display, Button1, Mod1Mask|Mod2Mask|Mod3Mask, frame.plate);
761 761
762 762
763 XGrabButton(display, Button1, Mod1Mask, frame.window, True, 763 XGrabButton(display, Button1, Mod1Mask, frame.window, True,
764 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, 764 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
@@ -768,7 +768,7 @@ void FluxboxWindow::grabButtons() {
768 grabButton(display, Button1, frame.window, fluxbox->getMoveCursor()); 768 grabButton(display, Button1, frame.window, fluxbox->getMoveCursor());
769 769
770 XGrabButton(display, Button2, Mod1Mask, frame.window, True, 770 XGrabButton(display, Button2, Mod1Mask, frame.window, True,
771 ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None); 771 ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
772 772
773 XGrabButton(display, Button3, Mod1Mask, frame.window, True, 773 XGrabButton(display, Button3, Mod1Mask, frame.window, True,
774 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, 774 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
@@ -2788,6 +2788,17 @@ void FluxboxWindow::mapNotifyEvent(XMapEvent *ne) {
2788 visible = true; 2788 visible = true;
2789 iconic = false; 2789 iconic = false;
2790 2790
2791 // Auto-group?
2792 if (!transient) {
2793 // Grab and clear the auto-group window
2794 FluxboxWindow* autoGroupWindow = screen->useAutoGroupWindow();
2795 if (autoGroupWindow) {
2796 Tab *groupTab = autoGroupWindow->getTab();
2797 if (groupTab)
2798 groupTab->addWindowToGroup(this);
2799 }
2800 }
2801
2791 fluxbox->ungrab(); 2802 fluxbox->ungrab();
2792 } 2803 }
2793} 2804}