aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--src/Screen.cc1
-rw-r--r--src/Screen.hh2
-rw-r--r--src/Window.cc86
-rw-r--r--src/Window.hh6
5 files changed, 61 insertions, 39 deletions
diff --git a/ChangeLog b/ChangeLog
index deab2d9..a64421f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
1 (Format: Year/Month/Day) 1 (Format: Year/Month/Day)
2Changes for 1.1: 2Changes for 1.1:
3*07/05/16:
4 * Added new resource session.screen<N>.noFocusWhileTypingDelay: <int> (Mark)
5 - specifies a time in milliseconds that new windows should not gain focus
6 while the user is typing in the focused window
7 Window.cc/hh Screen.cc/hh
3*07/05/13: 8*07/05/13:
4 * Added new placement policies {Row,Col}MinOverlapPlacement. They behave the 9 * Added new placement policies {Row,Col}MinOverlapPlacement. They behave the
5 same as {Row,Col}SmartPlacement when the window fits but fall back on 10 same as {Row,Col}SmartPlacement when the window fits but fall back on
diff --git a/src/Screen.cc b/src/Screen.cc
index 786daa1..2c24157 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -293,6 +293,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
293 resize_model(rm, BOTTOMRESIZE, scrname+".resizeMode", altscrname+".ResizeMode"), 293 resize_model(rm, BOTTOMRESIZE, scrname+".resizeMode", altscrname+".ResizeMode"),
294 tab_placement(rm, FbWinFrame::TOPLEFT, scrname+".tab.placement", altscrname+".Tab.Placement"), 294 tab_placement(rm, FbWinFrame::TOPLEFT, scrname+".tab.placement", altscrname+".Tab.Placement"),
295 windowmenufile(rm, "", scrname+".windowMenu", altscrname+".WindowMenu"), 295 windowmenufile(rm, "", scrname+".windowMenu", altscrname+".WindowMenu"),
296 typing_delay(rm, 0, scrname+".noFocusWhileTypingDelay", altscrname+".NoFocusWhileTypingDelay"),
296 user_follow_model(rm, FOLLOW_ACTIVE_WINDOW, scrname+".userFollowModel", altscrname+".UserFollowModel"), 297 user_follow_model(rm, FOLLOW_ACTIVE_WINDOW, scrname+".userFollowModel", altscrname+".UserFollowModel"),
297 workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"), 298 workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"),
298 edge_snap_threshold(rm, 0, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"), 299 edge_snap_threshold(rm, 0, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"),
diff --git a/src/Screen.hh b/src/Screen.hh
index b459f3f..2d1c31d 100644
--- a/src/Screen.hh
+++ b/src/Screen.hh
@@ -143,6 +143,7 @@ public:
143 143
144 ResizeModel getResizeModel() const { return *resource.resize_model; } 144 ResizeModel getResizeModel() const { return *resource.resize_model; }
145 145
146 inline unsigned int noFocusWhileTypingDelay() const { return *resource.typing_delay; }
146 inline FollowModel getUserFollowModel() const { return *resource.user_follow_model; } 147 inline FollowModel getUserFollowModel() const { return *resource.user_follow_model; }
147 148
148 inline const std::string &getScrollAction() const { return *resource.scroll_action; } 149 inline const std::string &getScrollAction() const { return *resource.scroll_action; }
@@ -567,6 +568,7 @@ private:
567 FbTk::Resource<ResizeModel> resize_model; 568 FbTk::Resource<ResizeModel> resize_model;
568 FbTk::Resource<FbWinFrame::TabPlacement> tab_placement; 569 FbTk::Resource<FbWinFrame::TabPlacement> tab_placement;
569 FbTk::Resource<std::string> windowmenufile; 570 FbTk::Resource<std::string> windowmenufile;
571 FbTk::Resource<unsigned int> typing_delay;
570 FbTk::Resource<FollowModel> user_follow_model; 572 FbTk::Resource<FollowModel> user_follow_model;
571 bool ordered_dither; 573 bool ordered_dither;
572 FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha, 574 FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha,
diff --git a/src/Window.cc b/src/Window.cc
index b9e26bd..b9dd4a6 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -1363,10 +1363,8 @@ bool FluxboxWindow::focus() {
1363 if (screen().currentWorkspaceID() != workspaceNumber() && !isStuck()) { 1363 if (screen().currentWorkspaceID() != workspaceNumber() && !isStuck()) {
1364 1364
1365 BScreen::FollowModel model = screen().getUserFollowModel(); 1365 BScreen::FollowModel model = screen().getUserFollowModel();
1366 if (model == BScreen::IGNORE_OTHER_WORKSPACES) { 1366 if (model == BScreen::IGNORE_OTHER_WORKSPACES)
1367 Fluxbox::instance()->attentionHandler().addAttention(*this);
1368 return false; 1367 return false;
1369 }
1370 1368
1371 // fetch the window to the current workspace 1369 // fetch the window to the current workspace
1372 if (model == BScreen::FETCH_ACTIVE_WINDOW || 1370 if (model == BScreen::FETCH_ACTIVE_WINDOW ||
@@ -1378,10 +1376,11 @@ bool FluxboxWindow::focus() {
1378 } 1376 }
1379 1377
1380 FluxboxWindow *cur = FocusControl::focusedFbWindow(); 1378 FluxboxWindow *cur = FocusControl::focusedFbWindow();
1381 if (cur && cur != this && cur->isFullscreen()) { 1379 WinClient *client = FocusControl::focusedWindow();
1382 Fluxbox::instance()->attentionHandler().addAttention(*this); 1380 if (cur && client && cur != this &&
1381 getRootTransientFor(m_client) != getRootTransientFor(client) &&
1382 (cur->isFullscreen() || cur->isTyping()))
1383 return false; 1383 return false;
1384 }
1385 1384
1386 if (isIconic()) { 1385 if (isIconic()) {
1387 deiconify(); 1386 deiconify();
@@ -1463,6 +1462,7 @@ void FluxboxWindow::hide(bool interrupt_moving) {
1463 1462
1464void FluxboxWindow::show() { 1463void FluxboxWindow::show() {
1465 frame().show(); 1464 frame().show();
1465 setState(NormalState, false);
1466} 1466}
1467 1467
1468void FluxboxWindow::toggleIconic() { 1468void FluxboxWindow::toggleIconic() {
@@ -1484,8 +1484,6 @@ void FluxboxWindow::iconify() {
1484 1484
1485 iconic = true; 1485 iconic = true;
1486 1486
1487 setState(IconicState, false);
1488
1489 hide(true); 1487 hide(true);
1490 1488
1491 screen().focusControl().setFocusBack(this); 1489 screen().focusControl().setFocusBack(this);
@@ -1494,9 +1492,6 @@ void FluxboxWindow::iconify() {
1494 const ClientList::iterator client_it_end = m_clientlist.end(); 1492 const ClientList::iterator client_it_end = m_clientlist.end();
1495 for (; client_it != client_it_end; ++client_it) { 1493 for (; client_it != client_it_end; ++client_it) {
1496 WinClient &client = *(*client_it); 1494 WinClient &client = *(*client_it);
1497 client.setEventMask(NoEventMask);
1498 client.hide();
1499 client.setEventMask(PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1500 if (client.transientFor() && 1495 if (client.transientFor() &&
1501 client.transientFor()->fbwindow()) { 1496 client.transientFor()->fbwindow()) {
1502 if (!client.transientFor()->fbwindow()->isIconic()) { 1497 if (!client.transientFor()->fbwindow()->isIconic()) {
@@ -1535,19 +1530,10 @@ void FluxboxWindow::deiconify(bool reassoc, bool do_raise) {
1535 m_blackbox_attrib.flags &= ~ATTRIB_HIDDEN; 1530 m_blackbox_attrib.flags &= ~ATTRIB_HIDDEN;
1536 iconic = false; 1531 iconic = false;
1537 1532
1538 setState(NormalState, false);
1539
1540 ClientList::iterator client_it = clientList().begin();
1541 ClientList::iterator client_it_end = clientList().end();
1542 for (; client_it != client_it_end; ++client_it) {
1543 (*client_it)->setEventMask(NoEventMask);
1544 (*client_it)->show();
1545 (*client_it)->setEventMask(PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1546 }
1547
1548 if (reassoc && !m_client->transients.empty()) { 1533 if (reassoc && !m_client->transients.empty()) {
1549 // deiconify all transients 1534 // deiconify all transients
1550 client_it = clientList().begin(); 1535 ClientList::iterator client_it = clientList().begin();
1536 ClientList::iterator client_it_end = clientList().end();
1551 for (; client_it != client_it_end; ++client_it) { 1537 for (; client_it != client_it_end; ++client_it) {
1552 //TODO: Can this get stuck in a loop? 1538 //TODO: Can this get stuck in a loop?
1553 WinClient::TransientList::iterator trans_it = 1539 WinClient::TransientList::iterator trans_it =
@@ -1863,9 +1849,6 @@ void FluxboxWindow::raise() {
1863 // get root window 1849 // get root window
1864 WinClient *client = getRootTransientFor(m_client); 1850 WinClient *client = getRootTransientFor(m_client);
1865 1851
1866 // if we don't have any root window use this as root
1867 if (client == 0)
1868 client = m_client;
1869 // if we have transient_for then we should put ourself last in 1852 // if we have transient_for then we should put ourself last in
1870 // transients list so we get raised last and thus gets above the other transients 1853 // transients list so we get raised last and thus gets above the other transients
1871 if (m_client->transientFor() && m_client != m_client->transientFor()->transientList().back()) { 1854 if (m_client->transientFor() && m_client != m_client->transientFor()->transientList().back()) {
@@ -1894,10 +1877,6 @@ void FluxboxWindow::lower() {
1894 // get root window 1877 // get root window
1895 WinClient *client = getRootTransientFor(m_client); 1878 WinClient *client = getRootTransientFor(m_client);
1896 1879
1897 // if we don't have any root window use this as root
1898 if (client == 0)
1899 client = m_client;
1900
1901 if (client->fbwindow()) 1880 if (client->fbwindow())
1902 lowerFluxboxWindow(*client->fbwindow()); 1881 lowerFluxboxWindow(*client->fbwindow());
1903} 1882}
@@ -1944,10 +1923,6 @@ void FluxboxWindow::moveToLayer(int layernum, bool force) {
1944 // get root window 1923 // get root window
1945 WinClient *client = getRootTransientFor(m_client); 1924 WinClient *client = getRootTransientFor(m_client);
1946 1925
1947 // if we don't have any root window use this as root
1948 if (client == 0)
1949 client = m_client;
1950
1951 FluxboxWindow *win = client->fbwindow(); 1926 FluxboxWindow *win = client->fbwindow();
1952 if (!win) return; 1927 if (!win) return;
1953 1928
@@ -2094,10 +2069,12 @@ void FluxboxWindow::setState(unsigned long new_state, bool setting_up) {
2094 ClientList::iterator it = clientList().begin(); 2069 ClientList::iterator it = clientList().begin();
2095 ClientList::iterator it_end = clientList().end(); 2070 ClientList::iterator it_end = clientList().end();
2096 for (; it != it_end; ++it) { 2071 for (; it != it_end; ++it) {
2072 (*it)->setEventMask(NoEventMask);
2097 if (new_state == IconicState) 2073 if (new_state == IconicState)
2098 (*it)->hide(); 2074 (*it)->hide();
2099 else if (new_state == NormalState) 2075 else if (new_state == NormalState)
2100 (*it)->show(); 2076 (*it)->show();
2077 (*it)->setEventMask(PropertyChangeMask | StructureNotifyMask | FocusChangeMask | KeyPressMask);
2101 } 2078 }
2102 2079
2103 saveBlackboxAttribs(); 2080 saveBlackboxAttribs();
@@ -2376,7 +2353,7 @@ void FluxboxWindow::mapNotifyEvent(XMapEvent &ne) {
2376 setState(NormalState, false); 2353 setState(NormalState, false);
2377 2354
2378 // we use m_focused as a signal that this should be focused when mapped 2355 // we use m_focused as a signal that this should be focused when mapped
2379 if (isFocused()) { 2356 if (m_focused) {
2380 m_focused = false; 2357 m_focused = false;
2381 focus(); 2358 focus();
2382 } 2359 }
@@ -2397,11 +2374,7 @@ void FluxboxWindow::unmapNotifyEvent(XUnmapEvent &ue) {
2397 cerr<<__FILE__<<"("<<__FUNCTION__<<"): title="<<client->title()<<endl; 2374 cerr<<__FILE__<<"("<<__FUNCTION__<<"): title="<<client->title()<<endl;
2398#endif // DEBUG 2375#endif // DEBUG
2399 2376
2400 // if window was in IconicState, then this event could have come from us 2377 restore(client, false);
2401 // unmapping the window -- but if send_event is set, then the client wants
2402 // to be withdrawn
2403 if (m_current_state == NormalState || ue.send_event)
2404 restore(client, false);
2405 2378
2406} 2379}
2407 2380
@@ -2602,6 +2575,41 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) {
2602 2575
2603} 2576}
2604 2577
2578// keep track of last keypress in window, so we can decide not to focusNew
2579void FluxboxWindow::keyPressEvent(XKeyEvent &ke) {
2580 // if there's a modifier key down, the user probably expects the new window
2581 if (FbTk::KeyUtil::instance().cleanMods(ke.state))
2582 return;
2583
2584 // we need to ignore modifier keys themselves, too
2585 KeySym ks;
2586 char keychar[1];
2587 XLookupString(&ke, keychar, 1, &ks, 0);
2588 if (IsModifierKey(ks))
2589 return;
2590
2591 // if the key was return/enter, the user probably expects the window
2592 // e.g., typed the command in a terminal
2593 if (ks == XK_KP_Enter || ks == XK_Return) {
2594 // we'll actually reset the time for this one
2595 m_last_keypress_time.tv_sec = 0;
2596 return;
2597 }
2598
2599 // otherwise, make a note that the user is typing
2600 gettimeofday(&m_last_keypress_time, 0);
2601}
2602
2603bool FluxboxWindow::isTyping() {
2604 timeval now;
2605 if (gettimeofday(&now, NULL) == -1)
2606 return false;
2607
2608 unsigned int diff = 1000*(now.tv_sec - m_last_keypress_time.tv_sec);
2609 diff += (now.tv_usec - m_last_keypress_time.tv_usec)/1000;
2610
2611 return (diff < screen().noFocusWhileTypingDelay());
2612}
2605 2613
2606void FluxboxWindow::buttonPressEvent(XButtonEvent &be) { 2614void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
2607 m_last_button_x = be.x_root; 2615 m_last_button_x = be.x_root;
diff --git a/src/Window.hh b/src/Window.hh
index c2f36c1..82a5f3f 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -38,6 +38,7 @@
38#include <X11/Xlib.h> 38#include <X11/Xlib.h>
39#include <X11/Xutil.h> 39#include <X11/Xutil.h>
40 40
41#include <sys/time.h>
41#include <vector> 42#include <vector>
42#include <string> 43#include <string>
43#include <memory> 44#include <memory>
@@ -337,6 +338,7 @@ public:
337 */ 338 */
338 //@{ 339 //@{
339 void handleEvent(XEvent &event); 340 void handleEvent(XEvent &event);
341 void keyPressEvent(XKeyEvent &ke);
340 void buttonPressEvent(XButtonEvent &be); 342 void buttonPressEvent(XButtonEvent &be);
341 void buttonReleaseEvent(XButtonEvent &be); 343 void buttonReleaseEvent(XButtonEvent &be);
342 void motionNotifyEvent(XMotionEvent &me); 344 void motionNotifyEvent(XMotionEvent &me);
@@ -419,6 +421,8 @@ public:
419 inline WinClient &winClient() { return *m_client; } 421 inline WinClient &winClient() { return *m_client; }
420 inline const WinClient &winClient() const { return *m_client; } 422 inline const WinClient &winClient() const { return *m_client; }
421 423
424 bool isTyping();
425
422 inline const FbTk::XLayerItem &layerItem() const { return m_frame.layerItem(); } 426 inline const FbTk::XLayerItem &layerItem() const { return m_frame.layerItem(); }
423 inline FbTk::XLayerItem &layerItem() { return m_frame.layerItem(); } 427 inline FbTk::XLayerItem &layerItem() { return m_frame.layerItem(); }
424 428
@@ -572,6 +576,8 @@ private:
572 int m_last_move_x, m_last_move_y; // handles last pos for non opaque moving 576 int m_last_move_x, m_last_move_y; // handles last pos for non opaque moving
573 unsigned int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window" 577 unsigned int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
574 578
579 timeval m_last_keypress_time;
580
575 unsigned int m_workspace_number; 581 unsigned int m_workspace_number;
576 unsigned long m_current_state; // NormalState | IconicState | Withdrawn 582 unsigned long m_current_state; // NormalState | IconicState | Withdrawn
577 583