diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2010-05-05 06:41:03 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2010-05-05 06:41:03 (GMT) |
commit | a10bab0f7cf9d41b9d462c643a3971c3ac348953 (patch) | |
tree | 3970736e2b58266e923e242e76eedae01261159c | |
parent | c1ed89194660be4419b73656e06b16b673003a9b (diff) | |
download | fluxbox_pavel-a10bab0f7cf9d41b9d462c643a3971c3ac348953.zip fluxbox_pavel-a10bab0f7cf9d41b9d462c643a3971c3ac348953.tar.bz2 |
added OnLeftGrip, OnRightGrip, OnWindowBorder modifiers for keys file
this allows to move some hardcoded keysbindings into the keys file and
makes the code simpler
-rw-r--r-- | src/Keys.cc | 10 | ||||
-rw-r--r-- | src/Keys.hh | 19 | ||||
-rw-r--r-- | src/Window.cc | 310 |
3 files changed, 170 insertions, 169 deletions
diff --git a/src/Keys.cc b/src/Keys.cc index 277dbe6..c050fd6 100644 --- a/src/Keys.cc +++ b/src/Keys.cc | |||
@@ -352,6 +352,10 @@ void Keys::loadDefaults() { | |||
352 | addBinding("OnDesktop Mouse2 :WorkspaceMenu"); | 352 | addBinding("OnDesktop Mouse2 :WorkspaceMenu"); |
353 | addBinding("OnDesktop Mouse3 :RootMenu"); | 353 | addBinding("OnDesktop Mouse3 :RootMenu"); |
354 | addBinding("OnTitlebar Mouse3 :WindowMenu"); | 354 | addBinding("OnTitlebar Mouse3 :WindowMenu"); |
355 | addBinding("OnTitlebar Move1 :StartMoving"); | ||
356 | addBinding("OnLeftGrip Move1 :StartResizing bottomleft"); | ||
357 | addBinding("OnRighttGrip Move1 :StartResizing bottomright"); | ||
358 | addBinding("OnWindowBorder Move1 :StartMoving"); | ||
355 | addBinding("Mod1 Tab :NextWindow"); | 359 | addBinding("Mod1 Tab :NextWindow"); |
356 | addBinding("Mod1 Shift Tab :PrevWindow"); | 360 | addBinding("Mod1 Shift Tab :PrevWindow"); |
357 | keyMode("default"); | 361 | keyMode("default"); |
@@ -402,6 +406,12 @@ bool Keys::addBinding(const string &linebuffer) { | |||
402 | context |= ON_WINDOW; | 406 | context |= ON_WINDOW; |
403 | else if (arg == "ontitlebar") | 407 | else if (arg == "ontitlebar") |
404 | context |= ON_TITLEBAR; | 408 | context |= ON_TITLEBAR; |
409 | else if (arg == "onwindowborder") | ||
410 | context |= ON_WINDOWBORDER; | ||
411 | else if (arg == "onleftgrip") | ||
412 | context |= ON_LEFTGRIP; | ||
413 | else if (arg == "onrightgrip") | ||
414 | context |= ON_RIGHTGRIP; | ||
405 | else if (arg == "double") | 415 | else if (arg == "double") |
406 | isdouble = true; | 416 | isdouble = true; |
407 | else if (arg != "none") { | 417 | else if (arg != "none") { |
diff --git a/src/Keys.hh b/src/Keys.hh index af64a1d..43f4445 100644 --- a/src/Keys.hh +++ b/src/Keys.hh | |||
@@ -42,14 +42,17 @@ public: | |||
42 | // it's ok if there is overlap; it will be worked out in t_key::find() | 42 | // it's ok if there is overlap; it will be worked out in t_key::find() |
43 | // eventHandlers should submit bitwise-or of contexts the event happened in | 43 | // eventHandlers should submit bitwise-or of contexts the event happened in |
44 | enum { | 44 | enum { |
45 | GLOBAL = 0x01, | 45 | GLOBAL = 1 << 0, |
46 | ON_DESKTOP = 0x02, | 46 | ON_DESKTOP = 1 << 1, |
47 | ON_TOOLBAR = 0x04, | 47 | ON_TOOLBAR = 1 << 2, |
48 | ON_ICONBUTTON = 0x08, | 48 | ON_ICONBUTTON = 1 << 3, |
49 | ON_TITLEBAR = 0x10, | 49 | ON_TITLEBAR = 1 << 4, |
50 | ON_WINDOW = 0x20, | 50 | ON_WINDOW = 1 << 5, |
51 | ON_TAB = 0x40, | 51 | ON_WINDOWBORDER = 1 << 6, |
52 | ON_SLIT = 0x80 | 52 | ON_LEFTGRIP = 1 << 7, |
53 | ON_RIGHTGRIP = 1 << 8, | ||
54 | ON_TAB = 1 << 9, | ||
55 | ON_SLIT = 1 << 10 | ||
53 | // and so on... | 56 | // and so on... |
54 | }; | 57 | }; |
55 | 58 | ||
diff --git a/src/Window.cc b/src/Window.cc index 586dc7b..427cd63 100644 --- a/src/Window.cc +++ b/src/Window.cc | |||
@@ -2406,205 +2406,193 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2406 | } | 2406 | } |
2407 | 2407 | ||
2408 | bool inside_titlebar = frame().insideTitlebar( me.window ); | 2408 | bool inside_titlebar = frame().insideTitlebar( me.window ); |
2409 | bool inside_grips = (me.window == frame().gripRight() || me.window == frame().gripLeft()); | ||
2410 | bool inside_border = false; | ||
2409 | 2411 | ||
2410 | if (Fluxbox::instance()->getIgnoreBorder() && m_attaching_tab == 0 | 2412 | if (!inside_grips) |
2411 | && !(isMoving() || isResizing())) { | 2413 | { |
2412 | |||
2413 | using RectangleUtil::insideBorder; | 2414 | using RectangleUtil::insideBorder; |
2414 | |||
2415 | int borderw = frame().window().borderWidth(); | 2415 | int borderw = frame().window().borderWidth(); |
2416 | |||
2417 | |||
2416 | //!! TODO(tabs): the below test ought to be in FbWinFrame | 2418 | //!! TODO(tabs): the below test ought to be in FbWinFrame |
2417 | // if mouse is currently on the window border, ignore it | ||
2418 | if ( ! insideBorder(frame(), me.x_root, me.y_root, borderw) && | ||
2419 | ( !frame().externalTabMode() || | ||
2420 | ! insideBorder(frame().tabcontainer(), me.x_root, me.y_root, borderw) ) | ||
2421 | 2419 | ||
2422 | || // or if mouse was on border when it was last clicked | 2420 | inside_border = |
2423 | 2421 | ||
2424 | ! insideBorder(frame(), m_last_button_x, m_last_button_y, borderw) && | 2422 | // if mouse is currently on the window border, ignore it |
2425 | ( ! frame().externalTabMode() || | 2423 | ! insideBorder(frame(), me.x_root, me.y_root, borderw) && |
2426 | ! insideBorder(frame().tabcontainer(), m_last_button_x, m_last_button_y, borderw ) ) ) { | 2424 | ( !frame().externalTabMode() || |
2425 | ! insideBorder(frame().tabcontainer(), me.x_root, me.y_root, borderw) ) | ||
2426 | |||
2427 | || // or if mouse was on border when it was last clicked | ||
2428 | |||
2429 | ! insideBorder(frame(), m_last_button_x, m_last_button_y, borderw) && | ||
2430 | ( ! frame().externalTabMode() || | ||
2431 | ! insideBorder(frame().tabcontainer(), m_last_button_x, m_last_button_y, borderw ) ); | ||
2432 | } | ||
2433 | |||
2434 | if (Fluxbox::instance()->getIgnoreBorder() && m_attaching_tab == 0 | ||
2435 | && !(isMoving() || isResizing())) { | ||
2436 | |||
2437 | if (inside_border) { | ||
2427 | return; | 2438 | return; |
2428 | } | 2439 | } |
2429 | } | 2440 | } |
2430 | 2441 | ||
2431 | 2442 | ||
2443 | int context = Keys::ON_WINDOW; | ||
2444 | if (inside_titlebar) { | ||
2445 | context = Keys::ON_TITLEBAR; | ||
2446 | } else if (inside_border) { | ||
2447 | context = Keys::ON_WINDOWBORDER; | ||
2448 | } else if (me.window == frame().gripRight()) { | ||
2449 | context = Keys::ON_RIGHTGRIP; | ||
2450 | } else if (me.window == frame().gripLeft()) { | ||
2451 | context = Keys::ON_LEFTGRIP; | ||
2452 | } | ||
2453 | |||
2454 | |||
2432 | // in case someone put MoveX :StartMoving etc into keys, we have | 2455 | // in case someone put MoveX :StartMoving etc into keys, we have |
2433 | // to activate it before doing the actual motionNotify code | 2456 | // to activate it before doing the actual motionNotify code |
2434 | Fluxbox::instance()->keys()->doAction(me.type, me.state, m_last_pressed_button, | 2457 | Fluxbox::instance()->keys()->doAction(me.type, me.state, m_last_pressed_button, context, &winClient(), me.time); |
2435 | inside_titlebar ? Keys::ON_TITLEBAR : Keys::ON_WINDOW, | 2458 | |
2436 | &winClient(), me.time); | 2459 | if (moving) { |
2437 | 2460 | ||
2438 | if (moving || ((me.state & Button1Mask) && functions.move && | 2461 | // Warp to next or previous workspace?, must have moved sideways some |
2439 | inside_titlebar && !isResizing() && m_attaching_tab == 0)) { | 2462 | int moved_x = me.x_root - m_last_resize_x; |
2463 | // save last event point | ||
2464 | m_last_resize_x = me.x_root; | ||
2465 | m_last_resize_y = me.y_root; | ||
2466 | |||
2467 | // undraw rectangle before warping workspaces | ||
2468 | if (!screen().doOpaqueMove()) { | ||
2469 | parent().drawRectangle(screen().rootTheme()->opGC(), | ||
2470 | m_last_move_x, m_last_move_y, | ||
2471 | frame().width() + 2*frame().window().borderWidth()-1, | ||
2472 | frame().height() + 2*frame().window().borderWidth()-1); | ||
2473 | } | ||
2440 | 2474 | ||
2441 | if (! isMoving()) { | 2475 | if (moved_x && screen().isWorkspaceWarping()) { |
2442 | startMoving(me.x_root, me.y_root); | 2476 | unsigned int cur_id = screen().currentWorkspaceID(); |
2443 | } else { | 2477 | unsigned int new_id = cur_id; |
2444 | // Warp to next or previous workspace?, must have moved sideways some | 2478 | const int warpPad = screen().getEdgeSnapThreshold(); |
2445 | int moved_x = me.x_root - m_last_resize_x; | 2479 | // 1) if we're inside the border threshold |
2446 | // save last event point | 2480 | // 2) if we moved in the right direction |
2447 | m_last_resize_x = me.x_root; | 2481 | if (me.x_root >= int(screen().width()) - warpPad - 1 && |
2448 | m_last_resize_y = me.y_root; | 2482 | moved_x > 0) { |
2449 | 2483 | //warp right | |
2450 | // undraw rectangle before warping workspaces | 2484 | new_id = (cur_id + 1) % screen().numberOfWorkspaces(); |
2451 | if (!screen().doOpaqueMove()) { | 2485 | m_last_resize_x = 0; // move mouse back to x=0 |
2452 | parent().drawRectangle(screen().rootTheme()->opGC(), | 2486 | } else if (me.x_root <= warpPad && |
2453 | m_last_move_x, m_last_move_y, | 2487 | moved_x < 0) { |
2454 | frame().width() + 2*frame().window().borderWidth()-1, | 2488 | //warp left |
2455 | frame().height() + 2*frame().window().borderWidth()-1); | 2489 | new_id = (cur_id + screen().numberOfWorkspaces() - 1) % screen().numberOfWorkspaces(); |
2490 | m_last_resize_x = screen().width() - 1; // move mouse to screen width - 1 | ||
2456 | } | 2491 | } |
2492 | if (new_id != cur_id) { | ||
2457 | 2493 | ||
2458 | if (moved_x && screen().isWorkspaceWarping()) { | 2494 | // remove motion events from queue to avoid repeated warps |
2459 | unsigned int cur_id = screen().currentWorkspaceID(); | 2495 | XEvent e; |
2460 | unsigned int new_id = cur_id; | 2496 | while (XCheckTypedEvent(display, MotionNotify, &e)) { |
2461 | const int warpPad = screen().getEdgeSnapThreshold(); | 2497 | // might as well update the y-coordinate |
2462 | // 1) if we're inside the border threshold | 2498 | m_last_resize_y = e.xmotion.y_root; |
2463 | // 2) if we moved in the right direction | ||
2464 | if (me.x_root >= int(screen().width()) - warpPad - 1 && | ||
2465 | moved_x > 0) { | ||
2466 | //warp right | ||
2467 | new_id = (cur_id + 1) % screen().numberOfWorkspaces(); | ||
2468 | m_last_resize_x = 0; // move mouse back to x=0 | ||
2469 | } else if (me.x_root <= warpPad && | ||
2470 | moved_x < 0) { | ||
2471 | //warp left | ||
2472 | new_id = (cur_id + screen().numberOfWorkspaces() - 1) % screen().numberOfWorkspaces(); | ||
2473 | m_last_resize_x = screen().width() - 1; // move mouse to screen width - 1 | ||
2474 | } | 2499 | } |
2475 | if (new_id != cur_id) { | ||
2476 | 2500 | ||
2477 | // remove motion events from queue to avoid repeated warps | 2501 | // move the pointer to (m_last_resize_x,m_last_resize_y) |
2478 | XEvent e; | 2502 | XWarpPointer(display, None, me.root, 0, 0, 0, 0, |
2479 | while (XCheckTypedEvent(display, MotionNotify, &e)) { | 2503 | m_last_resize_x, m_last_resize_y); |
2480 | // might as well update the y-coordinate | ||
2481 | m_last_resize_y = e.xmotion.y_root; | ||
2482 | } | ||
2483 | |||
2484 | // move the pointer to (m_last_resize_x,m_last_resize_y) | ||
2485 | XWarpPointer(display, None, me.root, 0, 0, 0, 0, | ||
2486 | m_last_resize_x, m_last_resize_y); | ||
2487 | 2504 | ||
2488 | if (screen().doOpaqueMove()) | 2505 | if (screen().doOpaqueMove()) |
2489 | screen().sendToWorkspace(new_id, this, true); | 2506 | screen().sendToWorkspace(new_id, this, true); |
2490 | else | 2507 | else |
2491 | screen().changeWorkspaceID(new_id, false); | 2508 | screen().changeWorkspaceID(new_id, false); |
2492 | } | ||
2493 | } | 2509 | } |
2510 | } | ||
2494 | 2511 | ||
2495 | int dx = m_last_resize_x - m_button_grab_x, | 2512 | int dx = m_last_resize_x - m_button_grab_x, |
2496 | dy = m_last_resize_y - m_button_grab_y; | 2513 | dy = m_last_resize_y - m_button_grab_y; |
2497 | 2514 | ||
2498 | dx -= frame().window().borderWidth(); | 2515 | dx -= frame().window().borderWidth(); |
2499 | dy -= frame().window().borderWidth(); | 2516 | dy -= frame().window().borderWidth(); |
2500 | 2517 | ||
2501 | // dx = current left side, dy = current top | 2518 | // dx = current left side, dy = current top |
2502 | doSnapping(dx, dy); | 2519 | doSnapping(dx, dy); |
2503 | 2520 | ||
2504 | if (!screen().doOpaqueMove()) { | 2521 | if (!screen().doOpaqueMove()) { |
2505 | parent().drawRectangle(screen().rootTheme()->opGC(), | 2522 | parent().drawRectangle(screen().rootTheme()->opGC(), |
2506 | dx, dy, | 2523 | dx, dy, |
2507 | frame().width() + 2*frame().window().borderWidth()-1, | 2524 | frame().width() + 2*frame().window().borderWidth()-1, |
2508 | frame().height() + 2*frame().window().borderWidth()-1); | 2525 | frame().height() + 2*frame().window().borderWidth()-1); |
2509 | m_last_move_x = dx; | 2526 | m_last_move_x = dx; |
2510 | m_last_move_y = dy; | 2527 | m_last_move_y = dy; |
2511 | } else { | 2528 | } else { |
2512 | //moveResize(dx, dy, frame().width(), frame().height()); | 2529 | //moveResize(dx, dy, frame().width(), frame().height()); |
2513 | // need to move the base window without interfering with transparency | 2530 | // need to move the base window without interfering with transparency |
2514 | frame().quietMoveResize(dx, dy, frame().width(), frame().height()); | 2531 | frame().quietMoveResize(dx, dy, frame().width(), frame().height()); |
2515 | } | 2532 | } |
2533 | |||
2534 | screen().showPosition(dx, dy); | ||
2535 | // end if moving | ||
2536 | } else if (resizing) { | ||
2516 | 2537 | ||
2517 | screen().showPosition(dx, dy); | 2538 | int old_resize_x = m_last_resize_x; |
2518 | } // end if moving | 2539 | int old_resize_y = m_last_resize_y; |
2519 | } else if (resizing || (m_attaching_tab == 0 && functions.resize && | 2540 | int old_resize_w = m_last_resize_w; |
2520 | (((me.state & Button1Mask) && | 2541 | int old_resize_h = m_last_resize_h; |
2521 | (me.window == frame().gripRight() || | 2542 | |
2522 | me.window == frame().gripLeft())) || | 2543 | int dx = me.x - m_button_grab_x; |
2523 | me.window == frame().window()))) { | 2544 | int dy = me.y - m_button_grab_y; |
2524 | 2545 | ||
2525 | if (! resizing) { | 2546 | if (m_resize_corner == LEFTTOP || m_resize_corner == LEFTBOTTOM || |
2526 | |||
2527 | ReferenceCorner resize_corner = RIGHTBOTTOM; | ||
2528 | if (me.window == frame().gripRight()) | ||
2529 | resize_corner = RIGHTBOTTOM; | ||
2530 | else if (me.window == frame().gripLeft()) | ||
2531 | resize_corner = LEFTBOTTOM; | ||
2532 | else // dragging border of window, so choose nearest corner | ||
2533 | resize_corner = getResizeDirection(me.x, me.y, QUADRANTRESIZE); | ||
2534 | |||
2535 | // We are grabbing frame window in startResizing | ||
2536 | // we need to translate coordinates to it. | ||
2537 | int start_x = me.x, start_y = me.y; | ||
2538 | Window child; | ||
2539 | XTranslateCoordinates(display, | ||
2540 | me.window, fbWindow().window(), | ||
2541 | start_x, start_y, | ||
2542 | &start_x, &start_y, | ||
2543 | &child); | ||
2544 | |||
2545 | startResizing(start_x, start_y, resize_corner); | ||
2546 | |||
2547 | } else if (resizing) { | ||
2548 | |||
2549 | int old_resize_x = m_last_resize_x; | ||
2550 | int old_resize_y = m_last_resize_y; | ||
2551 | int old_resize_w = m_last_resize_w; | ||
2552 | int old_resize_h = m_last_resize_h; | ||
2553 | |||
2554 | int dx = me.x - m_button_grab_x; | ||
2555 | int dy = me.y - m_button_grab_y; | ||
2556 | |||
2557 | if (m_resize_corner == LEFTTOP || m_resize_corner == LEFTBOTTOM || | ||
2558 | m_resize_corner == LEFT) { | 2547 | m_resize_corner == LEFT) { |
2559 | m_last_resize_w = frame().width() - dx; | 2548 | m_last_resize_w = frame().width() - dx; |
2560 | m_last_resize_x = frame().x() + dx; | 2549 | m_last_resize_x = frame().x() + dx; |
2561 | } | 2550 | } |
2562 | if (m_resize_corner == LEFTTOP || m_resize_corner == RIGHTTOP || | 2551 | if (m_resize_corner == LEFTTOP || m_resize_corner == RIGHTTOP || |
2563 | m_resize_corner == TOP) { | 2552 | m_resize_corner == TOP) { |
2564 | m_last_resize_h = frame().height() - dy; | 2553 | m_last_resize_h = frame().height() - dy; |
2565 | m_last_resize_y = frame().y() + dy; | 2554 | m_last_resize_y = frame().y() + dy; |
2566 | } | 2555 | } |
2567 | if (m_resize_corner == LEFTBOTTOM || m_resize_corner == BOTTOM || | 2556 | if (m_resize_corner == LEFTBOTTOM || m_resize_corner == BOTTOM || |
2568 | m_resize_corner == RIGHTBOTTOM) | 2557 | m_resize_corner == RIGHTBOTTOM) |
2569 | m_last_resize_h = frame().height() + dy; | 2558 | m_last_resize_h = frame().height() + dy; |
2570 | if (m_resize_corner == RIGHTBOTTOM || m_resize_corner == RIGHTTOP || | 2559 | if (m_resize_corner == RIGHTBOTTOM || m_resize_corner == RIGHTTOP || |
2571 | m_resize_corner == RIGHT) | 2560 | m_resize_corner == RIGHT) |
2572 | m_last_resize_w = frame().width() + dx; | 2561 | m_last_resize_w = frame().width() + dx; |
2573 | if (m_resize_corner == CENTER) { | 2562 | if (m_resize_corner == CENTER) { |
2574 | // dx or dy must be at least 2 | 2563 | // dx or dy must be at least 2 |
2575 | if (abs(dx) >= 2 || abs(dy) >= 2) { | 2564 | if (abs(dx) >= 2 || abs(dy) >= 2) { |
2576 | // take max and make it even | 2565 | // take max and make it even |
2577 | int diff = 2 * (max(dx, dy) / 2); | 2566 | int diff = 2 * (max(dx, dy) / 2); |
2578 | 2567 | ||
2579 | m_last_resize_h = frame().height() + diff; | 2568 | m_last_resize_h = frame().height() + diff; |
2580 | 2569 | ||
2581 | m_last_resize_w = frame().width() + diff; | 2570 | m_last_resize_w = frame().width() + diff; |
2582 | m_last_resize_x = frame().x() - diff/2; | 2571 | m_last_resize_x = frame().x() - diff/2; |
2583 | m_last_resize_y = frame().y() - diff/2; | 2572 | m_last_resize_y = frame().y() - diff/2; |
2584 | } | ||
2585 | } | 2573 | } |
2574 | } | ||
2586 | 2575 | ||
2587 | fixSize(); | 2576 | fixSize(); |
2588 | frame().displaySize(m_last_resize_w, m_last_resize_h); | 2577 | frame().displaySize(m_last_resize_w, m_last_resize_h); |
2589 | 2578 | ||
2590 | if (old_resize_x != m_last_resize_x || | 2579 | if (old_resize_x != m_last_resize_x || |
2591 | old_resize_y != m_last_resize_y || | 2580 | old_resize_y != m_last_resize_y || |
2592 | old_resize_w != m_last_resize_w || | 2581 | old_resize_w != m_last_resize_w || |
2593 | old_resize_h != m_last_resize_h ) { | 2582 | old_resize_h != m_last_resize_h ) { |
2594 | 2583 | ||
2595 | // draw over old rect | 2584 | // draw over old rect |
2596 | parent().drawRectangle(screen().rootTheme()->opGC(), | 2585 | parent().drawRectangle(screen().rootTheme()->opGC(), |
2597 | old_resize_x, old_resize_y, | 2586 | old_resize_x, old_resize_y, |
2598 | old_resize_w - 1 + 2 * frame().window().borderWidth(), | 2587 | old_resize_w - 1 + 2 * frame().window().borderWidth(), |
2599 | old_resize_h - 1 + 2 * frame().window().borderWidth()); | 2588 | old_resize_h - 1 + 2 * frame().window().borderWidth()); |
2600 | 2589 | ||
2601 | // draw resize rectangle | 2590 | // draw resize rectangle |
2602 | parent().drawRectangle(screen().rootTheme()->opGC(), | 2591 | parent().drawRectangle(screen().rootTheme()->opGC(), |
2603 | m_last_resize_x, m_last_resize_y, | 2592 | m_last_resize_x, m_last_resize_y, |
2604 | m_last_resize_w - 1 + 2 * frame().window().borderWidth(), | 2593 | m_last_resize_w - 1 + 2 * frame().window().borderWidth(), |
2605 | m_last_resize_h - 1 + 2 * frame().window().borderWidth()); | 2594 | m_last_resize_h - 1 + 2 * frame().window().borderWidth()); |
2606 | 2595 | ||
2607 | } | ||
2608 | } | 2596 | } |
2609 | } else if (m_attaching_tab != 0) { | 2597 | } else if (m_attaching_tab != 0) { |
2610 | // | 2598 | // |