1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 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: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 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 THE 17 // 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. 21 // 22 // File Name: Window.cpp 23 // Author: Adrian Oanca (e2joseph@hotpop.com) 24 // Description: A BWindow object represents a window that can be displayed 25 // on the screen, and that can be the target of user events 26 //------------------------------------------------------------------------------ 27 28 // System Includes ------------------------------------------------------------- 29 #include <BeBuild.h> 30 #include <InterfaceDefs.h> 31 #include <PropertyInfo.h> 32 #include <Handler.h> 33 #include <Looper.h> 34 #include <Application.h> 35 #include <Window.h> 36 #include <View.h> 37 #include <MenuBar.h> 38 #include <String.h> 39 #include <Screen.h> 40 #include <Button.h> 41 #include <MessageQueue.h> 42 #include <MessageRunner.h> 43 #include <Roster.h> 44 45 // Project Includes ------------------------------------------------------------ 46 #include <AppMisc.h> 47 #include <PortLink.h> 48 #include <PortMessage.h> 49 #include <Session.h> 50 #include <ServerProtocol.h> 51 #include <TokenSpace.h> 52 #include <MessageUtils.h> 53 #include <WindowAux.h> 54 55 // Standard Includes ----------------------------------------------------------- 56 #include <stdio.h> 57 #include <math.h> 58 #include <posix/math.h> 59 60 // Local Includes -------------------------------------------------------------- 61 62 // Local Defines --------------------------------------------------------------- 63 //#define DEBUG_WIN 64 #ifdef DEBUG_WIN 65 # include <stdio.h> 66 # define STRACE(x) printf x 67 #else 68 # define STRACE(x) ; 69 #endif 70 71 // Globals --------------------------------------------------------------------- 72 static property_info windowPropInfo[] = 73 { 74 { "Feel", { B_GET_PROPERTY, 0 }, 75 { B_DIRECT_SPECIFIER, 0 }, "Returns the current feel of the window.",0 }, 76 77 { "Feel", { B_SET_PROPERTY, 0 }, 78 { B_DIRECT_SPECIFIER, 0 }, "Sets the feel of the window.",0 }, 79 80 { "Flags", { B_GET_PROPERTY, 0 }, 81 { B_DIRECT_SPECIFIER, 0 }, "Returns the current flags of the window.",0 }, 82 83 { "Flags", { B_SET_PROPERTY, 0 }, 84 { B_DIRECT_SPECIFIER, 0 }, "Sets the window flags.",0 }, 85 86 { "Frame", { B_GET_PROPERTY, 0 }, 87 { B_DIRECT_SPECIFIER, 0 }, "Returns the window's frame rectangle.",0}, 88 89 { "Frame", { B_SET_PROPERTY, 0 }, 90 { B_DIRECT_SPECIFIER, 0 }, "Sets the window's frame rectangle.",0 }, 91 92 { "Hidden", { B_GET_PROPERTY, 0 }, 93 { B_DIRECT_SPECIFIER, 0 }, "Returns true if the window is hidden; false otherwise.",0}, 94 95 { "Hidden", { B_SET_PROPERTY, 0 }, 96 { B_DIRECT_SPECIFIER, 0 }, "Hides or shows the window.",0 }, 97 98 { "Look", { B_GET_PROPERTY, 0 }, 99 { B_DIRECT_SPECIFIER, 0 }, "Returns the current look of the window.",0}, 100 101 { "Look", { B_SET_PROPERTY, 0 }, 102 { B_DIRECT_SPECIFIER, 0 }, "Sets the look of the window.",0 }, 103 104 { "Title", { B_GET_PROPERTY, 0 }, 105 { B_DIRECT_SPECIFIER, 0 }, "Returns a string containing the window title.",0}, 106 107 { "Title", { B_SET_PROPERTY, 0 }, 108 { B_DIRECT_SPECIFIER, 0 }, "Sets the window title.",0 }, 109 110 { "Workspaces", { B_GET_PROPERTY, 0 }, 111 { B_DIRECT_SPECIFIER, 0 }, "Returns int32 bitfield of the workspaces in which the window appears.",0}, 112 113 { "Workspaces", { B_SET_PROPERTY, 0 }, 114 { B_DIRECT_SPECIFIER, 0 }, "Sets the workspaces in which the window appears.",0 }, 115 116 { "MenuBar", { 0 }, 117 { B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the key menu bar.",0 }, 118 119 { "View", { 0 }, 120 { 0 }, "Directs the scripting message to the top view without popping the current specifier.",0 }, 121 122 { "Minimize", { B_SET_PROPERTY, 0 }, 123 { B_DIRECT_SPECIFIER, 0 }, "Minimizes the window if \"data\" is true; restores otherwise.",0 }, 124 125 { 0, { 0 }, { 0 }, 0, 0 } 126 }; 127 //------------------------------------------------------------------------------ 128 129 // Constructors 130 //------------------------------------------------------------------------------ 131 BWindow::BWindow(BRect frame, 132 const char* title, 133 window_type type, 134 uint32 flags, 135 uint32 workspace) 136 : BLooper( title ) 137 { 138 #ifdef DEBUG_WIN 139 printf("BWindow::BWindow()\n"); 140 #endif 141 window_look look; 142 window_feel feel; 143 144 decomposeType(type, &look, &feel); 145 146 InitData( frame, title, look, feel, flags, workspace); 147 } 148 149 //------------------------------------------------------------------------------ 150 151 BWindow::BWindow(BRect frame, 152 const char* title, 153 window_look look, 154 window_feel feel, 155 uint32 flags, 156 uint32 workspace) 157 : BLooper( title ) 158 { 159 InitData( frame, title, look, feel, flags, workspace ); 160 } 161 162 //------------------------------------------------------------------------------ 163 164 BWindow::BWindow(BMessage* data) 165 : BLooper(data) 166 { 167 BMessage msg; 168 BArchivable *obj; 169 const char *title; 170 window_look look; 171 window_feel feel; 172 uint32 type; 173 uint32 workspaces; 174 175 data->FindRect("_frame", &fFrame); 176 data->FindString("_title", &title); 177 data->FindInt32("_wlook", (int32*)&look); 178 data->FindInt32("_wfeel", (int32*)&feel); 179 if ( data->FindInt32("_flags", (int32*)&fFlags) == B_OK ) 180 { } 181 else 182 fFlags = 0; 183 data->FindInt32("_wspace", (int32*)&workspaces); 184 185 if ( data->FindInt32("_type", (int32*)&type) == B_OK ){ 186 decomposeType( (window_type)type, &fLook, &fFeel ); 187 } 188 189 // connect to app_server and initialize data 190 InitData( fFrame, title, look, feel, fFlags, workspaces ); 191 192 if ( data->FindFloat("_zoom", 0, &fMaxZoomWidth) == B_OK ) 193 if ( data->FindFloat("_zoom", 1, &fMaxZoomHeight) == B_OK) 194 SetZoomLimits( fMaxZoomWidth, fMaxZoomHeight ); 195 196 if (data->FindFloat("_sizel", 0, &fMinWindWidth) == B_OK ) 197 if (data->FindFloat("_sizel", 1, &fMinWindHeight) == B_OK ) 198 if (data->FindFloat("_sizel", 2, &fMaxWindWidth) == B_OK ) 199 if (data->FindFloat("_sizel", 3, &fMaxWindHeight) == B_OK ) 200 SetSizeLimits( fMinWindWidth, fMaxWindWidth, 201 fMinWindHeight, fMaxWindHeight ); 202 203 if (data->FindInt64("_pulse", &fPulseRate) == B_OK ) 204 SetPulseRate( fPulseRate ); 205 206 int i = 0; 207 while ( data->FindMessage("_views", i++, &msg) == B_OK){ 208 obj = instantiate_object(&msg); 209 210 BView *child; 211 child = dynamic_cast<BView *>(obj); 212 if (child) 213 AddChild( child ); 214 } 215 } 216 217 //------------------------------------------------------------------------------ 218 219 BWindow::~BWindow(){ 220 // the following lines, remove all existing shortcuts and delete accelList 221 int32 noOfItems; 222 223 noOfItems = accelList.CountItems(); 224 for ( int index = noOfItems-1; index >= 0; index-- ) { 225 _BCmdKey *cmdKey; 226 227 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 228 229 accelList.RemoveItem(index); 230 231 delete cmdKey->message; 232 delete cmdKey; 233 } 234 235 // TODO: release other dinamicaly alocated objects 236 237 // disable pulsing 238 SetPulseRate( 0 ); 239 240 delete session; 241 delete_port( receive_port ); 242 } 243 244 //------------------------------------------------------------------------------ 245 246 BArchivable* BWindow::Instantiate(BMessage* data){ 247 248 if ( !validate_instantiation( data , "BWindow" ) ) 249 return NULL; 250 return new BWindow(data); 251 } 252 253 //------------------------------------------------------------------------------ 254 255 status_t BWindow::Archive(BMessage* data, bool deep) const{ 256 257 status_t retval; 258 259 retval = BLooper::Archive( data, deep ); 260 if (retval != B_OK) 261 return retval; 262 263 data->AddRect("_frame", fFrame); 264 data->AddString("_title", fTitle); 265 data->AddInt32("_wlook", fLook); 266 data->AddInt32("_wfeel", fFeel); 267 if (fFlags) 268 data->AddInt32("_flags", fFlags); 269 data->AddInt32("_wspace", (uint32)Workspaces()); 270 271 if ( !composeType(fLook, fFeel) ) 272 data->AddInt32("_type", (uint32)Type()); 273 274 if (fMaxZoomWidth != 32768.0 || fMaxZoomHeight != 32768.0) 275 { 276 data->AddFloat("_zoom", fMaxZoomWidth); 277 data->AddFloat("_zoom", fMaxZoomHeight); 278 } 279 280 if (fMinWindWidth != 0.0 || fMinWindHeight != 0.0 || 281 fMaxWindWidth != 32768.0 || fMaxWindHeight != 32768.0) 282 { 283 data->AddFloat("_sizel", fMinWindWidth); 284 data->AddFloat("_sizel", fMinWindHeight); 285 data->AddFloat("_sizel", fMaxWindWidth); 286 data->AddFloat("_sizel", fMaxWindHeight); 287 } 288 289 if (fPulseRate != 500000) 290 data->AddInt64("_pulse", fPulseRate); 291 292 if (deep) 293 { 294 int32 noOfViews = CountChildren(); 295 for (int i=0; i<noOfViews; i++){ 296 BMessage childArchive; 297 298 retval = ChildAt(i)->Archive( &childArchive, deep ); 299 if (retval == B_OK) 300 data->AddMessage( "_views", &childArchive ); 301 } 302 } 303 304 return B_OK; 305 } 306 307 //------------------------------------------------------------------------------ 308 309 void BWindow::Quit(){ 310 311 if (!IsLocked()) 312 { 313 const char* name = Name(); 314 if (!name) 315 name = "no-name"; 316 317 printf("ERROR - you must Lock a looper before calling Quit(), " 318 "team=%ld, looper=%s\n", Team(), name); 319 } 320 321 // Try to lock 322 if (!Lock()){ 323 // We're toast already 324 return; 325 } 326 327 while (!IsHidden()) { Hide(); } 328 329 // ... also its children 330 //detachTopView(); 331 STRACE(("Trying to stop connection...\n")); 332 // tell app_server, this window will finish execution 333 stopConnection(); 334 STRACE(("Connection stopped!\n")); 335 if (fFlags & B_QUIT_ON_WINDOW_CLOSE) 336 be_app->PostMessage( B_QUIT_REQUESTED ); 337 338 BLooper::Quit(); 339 } 340 341 //------------------------------------------------------------------------------ 342 343 void BWindow::AddChild(BView *child, BView *before){ 344 top_view->AddChild( child, before ); 345 } 346 347 //------------------------------------------------------------------------------ 348 349 bool BWindow::RemoveChild(BView *child){ 350 return top_view->RemoveChild( child ); 351 } 352 353 //------------------------------------------------------------------------------ 354 355 int32 BWindow::CountChildren() const{ 356 return top_view->CountChildren(); 357 } 358 359 //------------------------------------------------------------------------------ 360 361 BView* BWindow::ChildAt(int32 index) const{ 362 return top_view->ChildAt( index ); 363 } 364 365 //------------------------------------------------------------------------------ 366 367 void BWindow::Minimize(bool minimize){ 368 if (IsModal()) 369 return; 370 371 if (IsFloating()) 372 return; 373 374 Lock(); 375 session->WriteInt32( AS_WINDOW_MINIMIZE ); 376 session->WriteBool( minimize ); 377 session->Sync( ); 378 Unlock(); 379 } 380 //------------------------------------------------------------------------------ 381 382 status_t BWindow::SendBehind(const BWindow* window){ 383 384 if (!window) 385 return B_ERROR; 386 387 int32 rCode; 388 389 Lock(); 390 session->WriteInt32( AS_SEND_BEHIND ); 391 session->WriteInt32( _get_object_token_(window) ); 392 session->Sync(); 393 session->ReadInt32( &rCode ); 394 Unlock(); 395 396 return rCode == SERVER_TRUE? B_OK : B_ERROR; 397 } 398 399 //------------------------------------------------------------------------------ 400 401 void BWindow::Flush() const{ 402 const_cast<BWindow*>(this)->Lock(); 403 session->Sync(); 404 const_cast<BWindow*>(this)->Unlock(); 405 } 406 407 //------------------------------------------------------------------------------ 408 409 void BWindow::Sync() const{ 410 411 int32 rCode; 412 413 const_cast<BWindow*>(this)->Lock(); 414 session->WriteInt32( AS_SYNC ); 415 session->Sync(); 416 session->ReadInt32( &rCode ); 417 const_cast<BWindow*>(this)->Unlock(); 418 } 419 420 //------------------------------------------------------------------------------ 421 422 void BWindow::DisableUpdates(){ 423 424 Lock(); 425 session->WriteInt32( AS_DISABLE_UPDATES ); 426 session->Sync(); 427 Unlock(); 428 } 429 430 //------------------------------------------------------------------------------ 431 432 void BWindow::EnableUpdates(){ 433 434 Lock(); 435 session->WriteInt32( AS_ENABLE_UPDATES ); 436 session->Sync( ); 437 Unlock(); 438 } 439 440 //------------------------------------------------------------------------------ 441 442 void BWindow::BeginViewTransaction(){ 443 if ( !fInTransaction ){ 444 Lock(); 445 session->WriteInt32( AS_BEGIN_TRANSACTION ); 446 Unlock(); 447 448 fInTransaction = true; 449 } 450 } 451 452 //------------------------------------------------------------------------------ 453 454 void BWindow::EndViewTransaction(){ 455 if ( fInTransaction ){ 456 Lock(); 457 session->WriteInt32( AS_END_TRANSACTION ); 458 session->Sync(); 459 Unlock(); 460 461 fInTransaction = false; 462 } 463 } 464 465 //------------------------------------------------------------------------------ 466 467 bool BWindow::IsFront() const{ 468 if (IsActive()) 469 return true; 470 471 if (IsModal()) 472 return true; 473 474 return false; 475 } 476 477 //------------------------------------------------------------------------------ 478 479 void BWindow::MessageReceived( BMessage *msg ) 480 { 481 BMessage specifier; 482 int32 what; 483 const char* prop; 484 int32 index; 485 status_t err; 486 487 if (msg->HasSpecifiers()){ 488 489 err = msg->GetCurrentSpecifier(&index, &specifier, &what, &prop); 490 if (err == B_OK) 491 { 492 BMessage replyMsg; 493 494 switch (msg->what) 495 { 496 case B_GET_PROPERTY:{ 497 replyMsg.what = B_NO_ERROR; 498 replyMsg.AddInt32( "error", B_OK ); 499 500 if (strcmp(prop, "Feel") ==0 ) 501 { 502 replyMsg.AddInt32( "result", (uint32)Feel()); 503 } 504 else if (strcmp(prop, "Flags") ==0 ) 505 { 506 replyMsg.AddInt32( "result", Flags()); 507 } 508 else if (strcmp(prop, "Frame") ==0 ) 509 { 510 replyMsg.AddRect( "result", Frame()); 511 } 512 else if (strcmp(prop, "Hidden") ==0 ) 513 { 514 replyMsg.AddBool( "result", IsHidden()); 515 } 516 else if (strcmp(prop, "Look") ==0 ) 517 { 518 replyMsg.AddInt32( "result", (uint32)Look()); 519 } 520 else if (strcmp(prop, "Title") ==0 ) 521 { 522 replyMsg.AddString( "result", Title()); 523 } 524 else if (strcmp(prop, "Workspaces") ==0 ) 525 { 526 replyMsg.AddInt32( "result", Workspaces()); 527 } 528 }break; 529 530 case B_SET_PROPERTY:{ 531 if (strcmp(prop, "Feel") ==0 ) 532 { 533 uint32 newFeel; 534 if (msg->FindInt32( "data", (int32*)&newFeel ) == B_OK){ 535 SetFeel( (window_feel)newFeel ); 536 537 replyMsg.what = B_NO_ERROR; 538 replyMsg.AddInt32( "error", B_OK ); 539 } 540 else{ 541 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 542 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 543 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 544 } 545 } 546 547 else if (strcmp(prop, "Flags") ==0 ) 548 { 549 uint32 newFlags; 550 if (msg->FindInt32( "data", (int32*)&newFlags ) == B_OK){ 551 SetFlags( newFlags ); 552 553 replyMsg.what = B_NO_ERROR; 554 replyMsg.AddInt32( "error", B_OK ); 555 } 556 else{ 557 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 558 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 559 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 560 } 561 } 562 563 else if (strcmp(prop, "Frame") ==0 ) 564 { 565 BRect newFrame; 566 if (msg->FindRect( "data", &newFrame ) == B_OK){ 567 MoveTo( newFrame.LeftTop() ); 568 ResizeTo( newFrame.right, newFrame.bottom); 569 570 replyMsg.what = B_NO_ERROR; 571 replyMsg.AddInt32( "error", B_OK ); 572 } 573 else{ 574 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 575 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 576 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 577 } 578 } 579 580 else if (strcmp(prop, "Hidden") ==0 ) 581 { 582 bool newHiddenState; 583 if (msg->FindBool( "data", &newHiddenState ) == B_OK){ 584 if ( !IsHidden() && newHiddenState == true ){ 585 Hide(); 586 587 replyMsg.what = B_NO_ERROR; 588 replyMsg.AddInt32( "error", B_OK ); 589 590 } 591 else if ( IsHidden() && newHiddenState == false ){ 592 Show(); 593 594 replyMsg.what = B_NO_ERROR; 595 replyMsg.AddInt32( "error", B_OK ); 596 } 597 else{ 598 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 599 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 600 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 601 } 602 } 603 else{ 604 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 605 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 606 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 607 } 608 } 609 610 else if (strcmp(prop, "Look") ==0 ) 611 { 612 uint32 newLook; 613 if (msg->FindInt32( "data", (int32*)&newLook ) == B_OK){ 614 SetLook( (window_look)newLook ); 615 616 replyMsg.what = B_NO_ERROR; 617 replyMsg.AddInt32( "error", B_OK ); 618 } 619 else{ 620 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 621 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 622 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 623 } 624 } 625 626 else if (strcmp(prop, "Title") ==0 ) 627 { 628 const char *newTitle = NULL; 629 if (msg->FindString( "data", &newTitle ) == B_OK){ 630 SetTitle( newTitle ); 631 632 replyMsg.what = B_NO_ERROR; 633 replyMsg.AddInt32( "error", B_OK ); 634 } 635 else{ 636 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 637 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 638 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 639 } 640 delete newTitle; 641 } 642 643 else if (strcmp(prop, "Workspaces") ==0 ) 644 { 645 uint32 newWorkspaces; 646 if (msg->FindInt32( "data", (int32*)&newWorkspaces ) == B_OK){ 647 SetWorkspaces( newWorkspaces ); 648 649 replyMsg.what = B_NO_ERROR; 650 replyMsg.AddInt32( "error", B_OK ); 651 } 652 else{ 653 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 654 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 655 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 656 } 657 } 658 659 }break; 660 } 661 msg->SendReply( &replyMsg ); 662 } 663 else{ 664 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 665 replyMsg.AddInt32( "error" , B_BAD_SCRIPT_SYNTAX ); 666 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 667 668 msg->SendReply( &replyMsg ); 669 } 670 671 } // END: if (msg->HasSpecifiers()) 672 else 673 BLooper::MessageReceived( msg ); 674 } 675 676 //------------------------------------------------------------------------------ 677 678 void BWindow::DispatchMessage(BMessage *msg, BHandler *target) 679 { 680 if (!msg){ 681 BLooper::DispatchMessage( msg, target ); 682 return; 683 } 684 685 switch ( msg->what ) { 686 case B_ZOOM:{ 687 Zoom(); 688 break;} 689 690 case B_MINIMIZE:{ 691 bool minimize; 692 693 msg->FindBool("minimize", &minimize); 694 695 fMinimized = minimize; 696 Minimize( minimize ); 697 break;} 698 699 case B_WINDOW_RESIZED:{ 700 BPoint offset; 701 int32 width, height; 702 703 msg->FindInt32("width", &width); 704 msg->FindInt32("height", &height); 705 offset.x = width; 706 offset.y = height; 707 708 fFrame.SetRightBottom( fFrame.LeftTop() + offset ); 709 FrameResized( offset.x, offset.y ); 710 break;} 711 712 case B_WINDOW_MOVED:{ 713 BPoint origin; 714 715 msg->FindPoint("where", &origin); 716 717 fFrame.OffsetTo( origin ); 718 FrameMoved( origin ); 719 break;} 720 721 // this is NOT an app_server message and we have to be cautious 722 case B_WINDOW_MOVE_BY:{ 723 BPoint offset; 724 725 if (msg->FindPoint("data", &offset) == B_OK) 726 MoveBy( offset.x, offset.y ); 727 else 728 msg->SendReply( B_MESSAGE_NOT_UNDERSTOOD ); 729 break;} 730 731 // this is NOT an app_server message and we have to be cautious 732 case B_WINDOW_MOVE_TO:{ 733 BPoint origin; 734 735 if (msg->FindPoint("data", &origin) == B_OK) 736 MoveTo( origin ); 737 else 738 msg->SendReply( B_MESSAGE_NOT_UNDERSTOOD ); 739 break;} 740 741 case B_WINDOW_ACTIVATED:{ 742 bool active; 743 744 msg->FindBool("active", &active); 745 746 fActive = active; 747 handleActivation( active ); 748 break;} 749 750 case B_SCREEN_CHANGED:{ 751 BRect frame; 752 uint32 mode; 753 754 msg->FindRect("frame", &frame); 755 msg->FindInt32("mode", (int32*)&mode); 756 ScreenChanged( frame, (color_space)mode ); 757 break;} 758 759 case B_WORKSPACE_ACTIVATED:{ 760 uint32 workspace; 761 bool active; 762 763 msg->FindInt32( "workspace", (int32*)&workspace ); 764 msg->FindBool( "active", &active ); 765 WorkspaceActivated( workspace, active ); 766 break;} 767 768 case B_WORKSPACES_CHANGED:{ 769 uint32 oldWorkspace; 770 uint32 newWorkspace; 771 772 msg->FindInt32( "old", (int32*)&oldWorkspace ); 773 msg->FindInt32( "new", (int32*)&newWorkspace ); 774 WorkspacesChanged( oldWorkspace, newWorkspace ); 775 break;} 776 777 case B_KEY_DOWN:{ 778 uint32 modifiers; 779 int32 raw_char; 780 const char *string; 781 782 msg->FindInt32( "modifiers", (int32*)&modifiers ); 783 msg->FindInt32( "raw_char", &raw_char ); 784 msg->FindString( "bytes", &string ); 785 // TODO: it is NOT "bytes" field you should pass to KeyDown(), it is "byte" field. 786 if ( !handleKeyDown( raw_char, (uint32)modifiers) ) 787 fFocus->KeyDown( string, strlen(string)-1 ); 788 break;} 789 790 case B_KEY_UP:{ 791 const char *string; 792 793 msg->FindString( "bytes", &string ); 794 fFocus->KeyUp( string, strlen(string)-1 ); 795 break;} 796 797 case B_UNMAPPED_KEY_DOWN:{ 798 if (fFocus) 799 fFocus->MessageReceived( msg ); 800 break;} 801 802 case B_UNMAPPED_KEY_UP:{ 803 if (fFocus) 804 fFocus->MessageReceived( msg ); 805 break;} 806 807 case B_MODIFIERS_CHANGED:{ 808 if (fFocus) 809 fFocus->MessageReceived( msg ); 810 break;} 811 812 case B_MOUSE_WHEEL_CHANGED:{ 813 if (fFocus) 814 fFocus->MessageReceived( msg ); 815 break;} 816 817 case B_MOUSE_DOWN:{ 818 BPoint where; 819 uint32 modifiers; 820 uint32 buttons; 821 int32 clicks; 822 823 msg->FindPoint( "where", &where ); 824 msg->FindInt32( "modifiers", (int32*)&modifiers ); 825 msg->FindInt32( "buttons", (int32*)&buttons ); 826 msg->FindInt32( "clicks", &clicks ); 827 828 sendMessageUsingEventMask( B_MOUSE_DOWN, where ); 829 break;} 830 831 case B_MOUSE_UP:{ 832 BPoint where; 833 uint32 modifiers; 834 835 msg->FindPoint( "where", &where ); 836 msg->FindInt32( "modifiers", (int32*)&modifiers ); 837 838 sendMessageUsingEventMask( B_MOUSE_UP, where ); 839 break;} 840 841 case B_MOUSE_MOVED:{ 842 BPoint where; 843 uint32 buttons; 844 845 msg->FindPoint( "where", &where ); 846 msg->FindInt32( "buttons", (int32*)&buttons ); 847 848 sendMessageUsingEventMask( B_MOUSE_MOVED, where ); 849 break;} 850 851 case B_PULSE:{ 852 if (fPulseEnabled) 853 sendPulse( top_view ); 854 break;} 855 856 case B_QUIT_REQUESTED:{ 857 if (QuitRequested()) 858 Quit(); 859 break;} 860 861 case _UPDATE_:{ 862 BRect updateRect; 863 msg->FindRect("_rect", &updateRect); 864 865 // TODO: ADD this method: 866 //DrawViews( updateRect ); 867 break;} 868 869 case B_VIEW_MOVED:{ 870 BPoint where; 871 int32 token = B_NULL_TOKEN; 872 BView *view; 873 874 msg->FindPoint("where", &where); 875 msg->FindInt32("_token", &token); 876 msg->RemoveName("_token"); 877 878 view = findView(top_view, token); 879 if (view){ 880 STRACE(("Calling BView(%s)::FrameMoved( %f, %f )\n", view->Name(), where.x, where.y)); 881 view->FrameMoved( where ); 882 } 883 else 884 printf("***PANIC: BW: Can't find view with ID: %ld !***\n", token); 885 886 break;} 887 888 case B_VIEW_RESIZED:{ 889 float newWidth, 890 newHeight; 891 BPoint where; 892 int32 token = B_NULL_TOKEN; 893 BView *view; 894 895 msg->FindFloat("width", &newWidth); 896 msg->FindFloat("height", &newHeight); 897 msg->FindPoint("where", &where); 898 msg->FindInt32("_token", &token); 899 msg->RemoveName("_token"); 900 901 view = findView(top_view, token); 902 if (view){ 903 STRACE(("Calling BView(%s)::FrameResized( %f, %f )\n", view->Name(), newWidth, newHeight)); 904 view->FrameResized( newWidth, newHeight ); 905 } 906 else 907 printf("***PANIC: BW: Can't find view with ID: %ld !***\n", token); 908 909 break;} 910 911 default:{ 912 BLooper::DispatchMessage(msg, target); 913 break;} 914 } 915 } 916 917 //------------------------------------------------------------------------------ 918 919 void BWindow::FrameMoved(BPoint new_position){ 920 // does nothing 921 // Hook function 922 } 923 924 //------------------------------------------------------------------------------ 925 926 void BWindow::FrameResized(float new_width, float new_height){ 927 // does nothing 928 // Hook function 929 } 930 931 //------------------------------------------------------------------------------ 932 933 void BWindow::WorkspacesChanged(uint32 old_ws, uint32 new_ws){ 934 // does nothing 935 // Hook function 936 } 937 938 //------------------------------------------------------------------------------ 939 940 void BWindow::WorkspaceActivated(int32 ws, bool state){ 941 // does nothing 942 // Hook function 943 } 944 945 //------------------------------------------------------------------------------ 946 947 void BWindow::MenusBeginning(){ 948 // does nothing 949 // Hook function 950 } 951 952 //------------------------------------------------------------------------------ 953 954 void BWindow::MenusEnded(){ 955 // does nothing 956 // Hook function 957 } 958 959 //------------------------------------------------------------------------------ 960 961 void BWindow::SetSizeLimits(float minWidth, float maxWidth, 962 float minHeight, float maxHeight){ 963 int32 rCode; 964 965 if (minWidth > maxWidth) 966 return; 967 if (minHeight > maxHeight) 968 return; 969 970 Lock(); 971 session->WriteInt32( AS_SET_SIZE_LIMITS ); 972 session->WriteFloat( fMinWindWidth ); 973 session->WriteFloat( fMaxWindWidth ); 974 session->WriteFloat( fMinWindHeight ); 975 session->WriteFloat( fMaxWindHeight ); 976 session->Sync(); 977 session->ReadInt32( &rCode ); 978 Unlock(); 979 980 if (rCode == SERVER_TRUE){ 981 fMinWindHeight = minHeight; 982 fMinWindWidth = minWidth; 983 fMaxWindHeight = maxHeight; 984 fMaxWindWidth = maxWidth; 985 } 986 } 987 988 //------------------------------------------------------------------------------ 989 990 void BWindow::GetSizeLimits(float *minWidth, float *maxWidth, 991 float *minHeight, float *maxHeight){ 992 *minHeight = fMinWindHeight; 993 *minWidth = fMinWindWidth; 994 *maxHeight = fMaxWindHeight; 995 *maxWidth = fMaxWindWidth; 996 } 997 998 //------------------------------------------------------------------------------ 999 1000 void BWindow::SetZoomLimits(float maxWidth, float maxHeight){ 1001 if (maxWidth > fMaxWindWidth) 1002 maxWidth = fMaxWindWidth; 1003 else 1004 fMaxZoomWidth = maxWidth; 1005 1006 if (maxHeight > fMaxWindHeight) 1007 maxHeight = fMaxWindHeight; 1008 else 1009 fMaxZoomHeight = maxHeight; 1010 } 1011 1012 //------------------------------------------------------------------------------ 1013 1014 void BWindow::Zoom( BPoint rec_position, float rec_width, float rec_height){ 1015 1016 // this is also a Hook function! 1017 1018 MoveTo( rec_position ); 1019 ResizeTo( rec_width, rec_height ); 1020 } 1021 1022 //------------------------------------------------------------------------------ 1023 1024 void BWindow::Zoom(){ 1025 float minWidth, minHeight; 1026 BScreen screen; 1027 /* from BeBook: 1028 However, if the window's rectangle already matches these "zoom" dimensions 1029 (give or take a few pixels), Zoom() passes the window's previous 1030 ("non-zoomed") size and location. (??????) 1031 */ 1032 if (Frame().Width() == fMaxZoomWidth && Frame().Height() == fMaxZoomHeight) { 1033 BPoint position( Frame().left, Frame().top); 1034 Zoom( position, fMaxZoomWidth, fMaxZoomHeight ); 1035 return; 1036 } 1037 1038 /* from BeBook: 1039 The dimensions that non-virtual Zoom() passes to hook Zoom() are deduced from 1040 the smallest of three rectangles: 3) the screen rectangle, 1) the rectangle 1041 defined by SetZoomLimits(), 2) the rectangle defined by SetSizeLimits() 1042 */ 1043 // 1 1044 minHeight = fMaxZoomHeight; 1045 minWidth = fMaxZoomWidth; 1046 1047 // 2 1048 if ( fMaxWindHeight < minHeight ) { minHeight = fMaxWindHeight; } 1049 if ( fMaxWindWidth < minWidth ) { minWidth = fMaxWindWidth; } 1050 1051 // 3 1052 if ( screen.Frame().Width() < minWidth ) { minWidth = screen.Frame().Width(); } 1053 if ( screen.Frame().Height() < minHeight ) { minHeight = screen.Frame().Height(); } 1054 1055 Zoom( Frame().LeftTop(), minWidth, minHeight ); 1056 } 1057 1058 //------------------------------------------------------------------------------ 1059 1060 void BWindow::ScreenChanged(BRect screen_size, color_space depth){ 1061 // Hook function 1062 // does nothing 1063 } 1064 1065 //------------------------------------------------------------------------------ 1066 1067 void BWindow::SetPulseRate(bigtime_t rate){ 1068 if ( rate < 0 ) 1069 return; 1070 1071 if (fPulseRate == 0 && !fPulseEnabled){ 1072 fPulseRunner = new BMessageRunner( BMessenger(this), 1073 new BMessage( B_PULSE ), 1074 rate); 1075 fPulseRate = rate; 1076 fPulseEnabled = true; 1077 1078 return; 1079 } 1080 1081 if (rate == 0 && fPulseEnabled){ 1082 delete fPulseRunner; 1083 fPulseRunner = NULL; 1084 1085 fPulseRate = rate; 1086 fPulseEnabled = false; 1087 1088 return; 1089 } 1090 1091 fPulseRunner->SetInterval( rate ); 1092 } 1093 1094 //------------------------------------------------------------------------------ 1095 1096 bigtime_t BWindow::PulseRate() const{ 1097 return fPulseRate; 1098 } 1099 1100 //------------------------------------------------------------------------------ 1101 1102 void BWindow::AddShortcut( uint32 key, uint32 modifiers, BMessage* msg){ 1103 AddShortcut( key, modifiers, msg, this); 1104 } 1105 1106 //------------------------------------------------------------------------------ 1107 1108 void BWindow::AddShortcut( uint32 key, uint32 modifiers, BMessage* msg, BHandler* target){ 1109 /* 1110 NOTE: I'm not sure if it is OK to use 'key' 1111 */ 1112 if ( !msg ) 1113 return; 1114 1115 int64 when; 1116 _BCmdKey *cmdKey; 1117 1118 when = real_time_clock_usecs(); 1119 msg->AddInt64("when", when); 1120 1121 // TODO: make sure key is a lowercase char !!! 1122 1123 modifiers = modifiers | B_COMMAND_KEY; 1124 1125 cmdKey = new _BCmdKey; 1126 cmdKey->key = key; 1127 cmdKey->modifiers = modifiers; 1128 cmdKey->message = msg; 1129 if (target == NULL) 1130 cmdKey->targetToken = B_ANY_TOKEN; 1131 else 1132 cmdKey->targetToken = _get_object_token_(target); 1133 1134 // removes the shortcut from accelList if it exists! 1135 RemoveShortcut( key, modifiers ); 1136 1137 accelList.AddItem( cmdKey ); 1138 1139 } 1140 1141 //------------------------------------------------------------------------------ 1142 1143 void BWindow::RemoveShortcut(uint32 key, uint32 modifiers){ 1144 int32 index; 1145 1146 modifiers = modifiers | B_COMMAND_KEY; 1147 1148 index = findShortcut( key, modifiers ); 1149 if ( index >=0 ) { 1150 _BCmdKey *cmdKey; 1151 1152 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 1153 1154 accelList.RemoveItem(index); 1155 1156 delete cmdKey->message; 1157 delete cmdKey; 1158 } 1159 } 1160 1161 //------------------------------------------------------------------------------ 1162 1163 BButton* BWindow::DefaultButton() const{ 1164 return fDefaultButton; 1165 } 1166 1167 //------------------------------------------------------------------------------ 1168 1169 void BWindow::SetDefaultButton(BButton* button){ 1170 /* 1171 Note: for developers! 1172 He he, if you really want to understand what is happens here, take a piece of 1173 paper and start taking possible values and then walk with them through 1174 the code. 1175 */ 1176 BButton *aux; 1177 1178 if ( fDefaultButton == button ) 1179 return; 1180 1181 if ( fDefaultButton ){ 1182 aux = fDefaultButton; 1183 fDefaultButton = NULL; 1184 aux->MakeDefault( false ); 1185 aux->Invalidate(); 1186 } 1187 1188 if ( button == NULL ){ 1189 fDefaultButton = NULL; 1190 return; 1191 } 1192 1193 fDefaultButton = button; 1194 fDefaultButton->MakeDefault( true ); 1195 fDefaultButton->Invalidate(); 1196 } 1197 1198 //------------------------------------------------------------------------------ 1199 1200 bool BWindow::NeedsUpdate() const{ 1201 1202 int32 rCode; 1203 1204 const_cast<BWindow*>(this)->Lock(); 1205 session->WriteInt32( AS_NEEDS_UPDATE ); 1206 session->Sync(); 1207 session->ReadInt32( &rCode ); 1208 const_cast<BWindow*>(this)->Unlock(); 1209 1210 return rCode == SERVER_TRUE; 1211 } 1212 1213 //------------------------------------------------------------------------------ 1214 1215 void BWindow::UpdateIfNeeded(){ 1216 // works only from this thread 1217 if (find_thread(NULL) == Thread()){ 1218 Sync(); 1219 drawAllViews( top_view ); 1220 } 1221 } 1222 1223 //------------------------------------------------------------------------------ 1224 1225 BView* BWindow::FindView(const char* viewName) const{ 1226 1227 return findView( top_view, viewName ); 1228 } 1229 1230 //------------------------------------------------------------------------------ 1231 1232 BView* BWindow::FindView(BPoint point) const{ 1233 1234 return findView( top_view, point ); 1235 } 1236 1237 //------------------------------------------------------------------------------ 1238 1239 BView* BWindow::CurrentFocus() const{ 1240 return fFocus; 1241 } 1242 1243 //------------------------------------------------------------------------------ 1244 1245 void BWindow::Activate(bool active){ 1246 if (IsHidden()) 1247 return; 1248 1249 Lock(); 1250 session->WriteInt32( AS_ACTIVATE_WINDOW ); 1251 session->WriteBool( active ); 1252 session->Sync( ); 1253 Unlock(); 1254 } 1255 1256 //------------------------------------------------------------------------------ 1257 1258 void BWindow::WindowActivated(bool state){ 1259 // hook function 1260 // does nothing 1261 } 1262 1263 //------------------------------------------------------------------------------ 1264 1265 void BWindow::ConvertToScreen(BPoint* pt) const{ 1266 pt->x += fFrame.left; 1267 pt->y += fFrame.top; 1268 } 1269 1270 //------------------------------------------------------------------------------ 1271 1272 BPoint BWindow::ConvertToScreen(BPoint pt) const{ 1273 pt.x += fFrame.left; 1274 pt.y += fFrame.top; 1275 1276 return pt; 1277 } 1278 1279 //------------------------------------------------------------------------------ 1280 1281 void BWindow::ConvertFromScreen(BPoint* pt) const{ 1282 pt->x -= fFrame.left; 1283 pt->y -= fFrame.top; 1284 } 1285 1286 //------------------------------------------------------------------------------ 1287 1288 BPoint BWindow::ConvertFromScreen(BPoint pt) const{ 1289 pt.x -= fFrame.left; 1290 pt.y -= fFrame.top; 1291 1292 return pt; 1293 } 1294 1295 //------------------------------------------------------------------------------ 1296 1297 void BWindow::ConvertToScreen(BRect* rect) const{ 1298 rect->top += fFrame.top; 1299 rect->left += fFrame.left; 1300 rect->bottom += fFrame.top; 1301 rect->right += fFrame.left; 1302 } 1303 1304 //------------------------------------------------------------------------------ 1305 1306 BRect BWindow::ConvertToScreen(BRect rect) const{ 1307 rect.top += fFrame.top; 1308 rect.left += fFrame.left; 1309 rect.bottom += fFrame.top; 1310 rect.right += fFrame.left; 1311 1312 return rect; 1313 } 1314 1315 //------------------------------------------------------------------------------ 1316 1317 void BWindow::ConvertFromScreen(BRect* rect) const{ 1318 rect->top -= fFrame.top; 1319 rect->left -= fFrame.left; 1320 rect->bottom -= fFrame.top; 1321 rect->right -= fFrame.left; 1322 } 1323 1324 //------------------------------------------------------------------------------ 1325 1326 BRect BWindow::ConvertFromScreen(BRect rect) const{ 1327 rect.top -= fFrame.top; 1328 rect.left -= fFrame.left; 1329 rect.bottom -= fFrame.top; 1330 rect.right -= fFrame.left; 1331 1332 return rect; 1333 } 1334 1335 //------------------------------------------------------------------------------ 1336 1337 bool BWindow::IsMinimized() const{ 1338 // Hiding takes precendence over minimization!!! 1339 if ( IsHidden() ) 1340 return false; 1341 1342 return fMinimized; 1343 } 1344 1345 //------------------------------------------------------------------------------ 1346 1347 BRect BWindow::Bounds() const{ 1348 BRect bounds( 0.0, 0.0, fFrame.Width(), fFrame.Height() ); 1349 return bounds; 1350 } 1351 1352 //------------------------------------------------------------------------------ 1353 1354 BRect BWindow::Frame() const{ 1355 return fFrame; 1356 } 1357 1358 //------------------------------------------------------------------------------ 1359 1360 const char* BWindow::Title() const{ 1361 return fTitle; 1362 } 1363 1364 //------------------------------------------------------------------------------ 1365 1366 void BWindow::SetTitle(const char* title){ 1367 if (!title) 1368 return; 1369 1370 if (fTitle){ 1371 delete fTitle; 1372 fTitle = NULL; 1373 } 1374 1375 fTitle = strdup( title ); 1376 1377 // we will change BWindow's thread name to "w>window_title" 1378 int32 length; 1379 length = strlen( fTitle ); 1380 1381 char *threadName; 1382 threadName = new char[32]; 1383 strcpy(threadName, "w>"); 1384 strncat(threadName, fTitle, (length>=29) ? 29: length); 1385 1386 // if the message loop has been started... 1387 if (Thread() != B_ERROR ){ 1388 SetName( threadName ); 1389 rename_thread( Thread(), threadName ); 1390 1391 // we notify the app_server so we can actually see the change 1392 Lock(); 1393 session->WriteInt32( AS_WINDOW_TITLE); 1394 session->WriteString( fTitle ); 1395 session->Sync( ); 1396 Unlock(); 1397 } 1398 else 1399 SetName( threadName ); 1400 } 1401 1402 //------------------------------------------------------------------------------ 1403 1404 bool BWindow::IsActive() const{ 1405 return fActive; 1406 } 1407 1408 //------------------------------------------------------------------------------ 1409 1410 void BWindow::SetKeyMenuBar(BMenuBar* bar){ 1411 fKeyMenuBar = bar; 1412 } 1413 1414 //------------------------------------------------------------------------------ 1415 1416 BMenuBar* BWindow::KeyMenuBar() const{ 1417 return fKeyMenuBar; 1418 } 1419 1420 //------------------------------------------------------------------------------ 1421 1422 bool BWindow::IsModal() const{ 1423 if ( fFeel == B_MODAL_SUBSET_WINDOW_FEEL) 1424 return true; 1425 if ( fFeel == B_MODAL_APP_WINDOW_FEEL) 1426 return true; 1427 if ( fFeel == B_MODAL_ALL_WINDOW_FEEL) 1428 return true; 1429 1430 return false; 1431 1432 } 1433 1434 //------------------------------------------------------------------------------ 1435 1436 bool BWindow::IsFloating() const{ 1437 if ( fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) 1438 return true; 1439 if ( fFeel == B_FLOATING_APP_WINDOW_FEEL) 1440 return true; 1441 if ( fFeel == B_FLOATING_ALL_WINDOW_FEEL) 1442 return true; 1443 1444 return false; 1445 } 1446 1447 //------------------------------------------------------------------------------ 1448 1449 status_t BWindow::AddToSubset(BWindow* window){ 1450 if ( !window ) 1451 return B_ERROR; 1452 1453 int32 rCode; 1454 1455 if (window->Feel() == B_NORMAL_WINDOW_FEEL && 1456 (fFeel == B_MODAL_SUBSET_WINDOW_FEEL || 1457 fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)){ 1458 1459 team_id team = Team(); 1460 1461 Lock(); 1462 session->WriteInt32( AS_ADD_TO_SUBSET ); 1463 session->WriteInt32( _get_object_token_(window) ); 1464 session->WriteData( &team, sizeof(team_id) ); 1465 session->Sync(); 1466 session->ReadInt32( &rCode ); 1467 Unlock(); 1468 1469 return rCode == SERVER_TRUE? B_OK : B_ERROR; 1470 } 1471 1472 return B_ERROR; 1473 } 1474 1475 //------------------------------------------------------------------------------ 1476 1477 status_t BWindow::RemoveFromSubset(BWindow* window){ 1478 if ( !window ) 1479 return B_ERROR; 1480 1481 int32 rCode; 1482 1483 if (window->Feel() == B_NORMAL_WINDOW_FEEL && 1484 (fFeel == B_MODAL_SUBSET_WINDOW_FEEL || 1485 fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)){ 1486 1487 team_id team = Team(); 1488 1489 Lock(); 1490 session->WriteInt32( AS_REM_FROM_SUBSET ); 1491 session->WriteInt32( _get_object_token_(window) ); 1492 session->WriteData( &team, sizeof(team_id) ); 1493 session->Sync(); 1494 session->ReadInt32( &rCode ); 1495 Unlock(); 1496 1497 return rCode == SERVER_TRUE? B_OK : B_ERROR; 1498 } 1499 1500 return B_ERROR; 1501 } 1502 1503 //------------------------------------------------------------------------------ 1504 1505 status_t BWindow::Perform(perform_code d, void* arg){ 1506 return BLooper::Perform( d, arg ); 1507 } 1508 1509 //------------------------------------------------------------------------------ 1510 1511 status_t BWindow::SetType(window_type type){ 1512 decomposeType(type, &fLook, &fFeel); 1513 status_t stat1, stat2; 1514 1515 stat1=SetLook( fLook ); 1516 stat2=SetFeel( fFeel ); 1517 1518 if(stat1==B_OK && stat2==B_OK) 1519 return B_OK; 1520 return B_ERROR; 1521 } 1522 1523 //------------------------------------------------------------------------------ 1524 1525 window_type BWindow::Type() const{ 1526 return composeType( fLook, fFeel ); 1527 } 1528 1529 //------------------------------------------------------------------------------ 1530 1531 status_t BWindow::SetLook(window_look look){ 1532 1533 int32 rCode; 1534 1535 Lock(); 1536 session->WriteInt32( AS_SET_LOOK ); 1537 session->WriteInt32( (int32)look ); 1538 session->Sync(); 1539 session->ReadInt32( &rCode ); 1540 Unlock(); 1541 1542 if (rCode == SERVER_TRUE){ 1543 fLook = look; 1544 return B_OK; 1545 } 1546 1547 return B_ERROR; 1548 } 1549 1550 //------------------------------------------------------------------------------ 1551 1552 window_look BWindow::Look() const{ 1553 return fLook; 1554 } 1555 1556 //------------------------------------------------------------------------------ 1557 1558 status_t BWindow::SetFeel(window_feel feel){ 1559 /* TODO: See what happens when a window that is part of a subset, changes its 1560 feel!? should it be removed from the subset??? 1561 */ 1562 int32 rCode; 1563 1564 Lock(); 1565 session->WriteInt32( AS_SET_FEEL ); 1566 session->WriteInt32( (int32)feel ); 1567 session->Sync(); 1568 session->ReadInt32( &rCode ); 1569 Unlock(); 1570 1571 if (rCode == SERVER_TRUE){ 1572 fFeel = feel; 1573 return B_OK; 1574 } 1575 1576 return B_ERROR; 1577 } 1578 1579 //------------------------------------------------------------------------------ 1580 1581 window_feel BWindow::Feel() const{ 1582 return fFeel; 1583 } 1584 1585 //------------------------------------------------------------------------------ 1586 1587 status_t BWindow::SetFlags(uint32 flags){ 1588 1589 int32 rCode; 1590 1591 Lock(); 1592 session->WriteInt32( AS_SET_FLAGS ); 1593 session->WriteUInt32( flags ); 1594 session->Sync(); 1595 session->ReadInt32( &rCode ); 1596 Unlock(); 1597 1598 if (rCode == SERVER_TRUE){ 1599 fFlags = flags; 1600 return B_OK; 1601 } 1602 1603 return B_ERROR; 1604 } 1605 1606 //------------------------------------------------------------------------------ 1607 1608 uint32 BWindow::Flags() const{ 1609 return fFlags; 1610 } 1611 1612 //------------------------------------------------------------------------------ 1613 1614 status_t BWindow::SetWindowAlignment(window_alignment mode, 1615 int32 h, int32 hOffset, 1616 int32 width, int32 widthOffset, 1617 int32 v, int32 vOffset, 1618 int32 height, int32 heightOffset) 1619 { 1620 if ( !( (mode && B_BYTE_ALIGNMENT) || 1621 (mode && B_PIXEL_ALIGNMENT) ) ) 1622 { 1623 return B_ERROR; 1624 } 1625 1626 if ( 0 <= hOffset && hOffset <=h ) 1627 return B_ERROR; 1628 1629 if ( 0 <= vOffset && vOffset <=v ) 1630 return B_ERROR; 1631 1632 if ( 0 <= widthOffset && widthOffset <=width ) 1633 return B_ERROR; 1634 1635 if ( 0 <= heightOffset && heightOffset <=height ) 1636 return B_ERROR; 1637 1638 // TODO: test if hOffset = 0 and set it to 1 if true. 1639 int32 rCode; 1640 1641 Lock(); 1642 session->WriteInt32( AS_SET_ALIGNMENT ); 1643 session->WriteInt32( (int32)mode ); 1644 session->WriteInt32( h ); 1645 session->WriteInt32( hOffset ); 1646 session->WriteInt32( width ); 1647 session->WriteInt32( widthOffset ); 1648 session->WriteInt32( v ); 1649 session->WriteInt32( vOffset ); 1650 session->WriteInt32( height ); 1651 session->WriteInt32( heightOffset ); 1652 session->Sync(); 1653 session->ReadInt32( &rCode ); 1654 Unlock(); 1655 1656 if ( rCode == SERVER_TRUE){ 1657 return B_NO_ERROR; 1658 } 1659 1660 return B_ERROR; 1661 } 1662 1663 //------------------------------------------------------------------------------ 1664 1665 status_t BWindow::GetWindowAlignment(window_alignment* mode, 1666 int32* h, int32* hOffset, 1667 int32* width, int32* widthOffset, 1668 int32* v, int32* vOffset, 1669 int32* height, int32* heightOffset) const 1670 { 1671 int32 rCode; 1672 1673 const_cast<BWindow*>(this)->Lock(); 1674 session->WriteInt32( AS_GET_ALIGNMENT ); 1675 session->Sync(); 1676 session->ReadInt32( &rCode ); 1677 1678 if (rCode == SERVER_TRUE){ 1679 session->ReadInt32( (int32*)mode ); 1680 session->ReadInt32( h ); 1681 session->ReadInt32( hOffset ); 1682 session->ReadInt32( width ); 1683 session->ReadInt32( widthOffset ); 1684 session->ReadInt32( v ); 1685 session->ReadInt32( hOffset ); 1686 session->ReadInt32( height ); 1687 session->ReadInt32( heightOffset ); 1688 1689 return B_NO_ERROR; 1690 } 1691 const_cast<BWindow*>(this)->Unlock(); 1692 1693 return B_ERROR; 1694 } 1695 1696 //------------------------------------------------------------------------------ 1697 1698 uint32 BWindow::Workspaces() const{ 1699 uint32 workspaces; 1700 1701 const_cast<BWindow*>(this)->Lock(); 1702 session->WriteInt32( AS_GET_WORKSPACES ); 1703 session->Sync(); 1704 session->ReadInt32( (int32*)&workspaces ); 1705 const_cast<BWindow*>(this)->Unlock(); 1706 1707 return workspaces; 1708 } 1709 1710 //------------------------------------------------------------------------------ 1711 1712 void BWindow::SetWorkspaces(uint32 workspaces){ 1713 1714 Lock(); 1715 session->WriteInt32( AS_SET_WORKSPACES ); 1716 session->WriteInt32( (int32)workspaces ); 1717 session->Sync( ); 1718 Unlock(); 1719 } 1720 1721 //------------------------------------------------------------------------------ 1722 1723 BView* BWindow::LastMouseMovedView() const{ 1724 return fLastMouseMovedView; 1725 } 1726 1727 //------------------------------------------------------------------------------ 1728 1729 void BWindow::MoveBy(float dx, float dy){ 1730 1731 BPoint offset( dx, dy ); 1732 1733 MoveTo( fFrame.LeftTop() + offset ); 1734 } 1735 1736 //------------------------------------------------------------------------------ 1737 1738 void BWindow::MoveTo( BPoint point ){ 1739 MoveTo( point.x, point.y ); 1740 } 1741 1742 //------------------------------------------------------------------------------ 1743 1744 void BWindow::MoveTo(float x, float y){ 1745 1746 Lock(); 1747 session->WriteInt32( AS_WINDOW_MOVE ); 1748 session->WriteFloat( x ); 1749 session->WriteFloat( y ); 1750 session->Sync(); 1751 Unlock(); 1752 } 1753 1754 //------------------------------------------------------------------------------ 1755 1756 void BWindow::ResizeBy(float dx, float dy){ 1757 1758 // stay in minimum & maximum frame limits 1759 (fFrame.Width() + dx) < fMinWindWidth ? fMinWindWidth : fFrame.Width() + dx; 1760 (fFrame.Width() + dx) > fMaxWindWidth ? fMaxWindWidth : fFrame.Width() + dx; 1761 1762 (fFrame.Height() + dy) < fMinWindHeight ? fMinWindHeight : fFrame.Height() + dy; 1763 (fFrame.Height() + dy) > fMaxWindHeight ? fMaxWindHeight : fFrame.Height() + dy; 1764 1765 ResizeTo( fFrame.Width() + dx, fFrame.Height() + dy ); 1766 } 1767 1768 //------------------------------------------------------------------------------ 1769 1770 void BWindow::ResizeTo(float width, float height){ 1771 1772 // stay in minimum & maximum frame limits 1773 width = (width < fMinWindWidth) ? fMinWindWidth : width; 1774 width = (width > fMaxWindWidth) ? fMaxWindWidth : width; 1775 1776 height = (height < fMinWindHeight) ? fMinWindHeight : height; 1777 height = (height > fMaxWindHeight) ? fMaxWindHeight : height; 1778 1779 Lock(); 1780 session->WriteInt32( AS_WINDOW_RESIZE ); 1781 session->WriteFloat( width ); 1782 session->WriteFloat( height ); 1783 session->Sync( ); 1784 Unlock(); 1785 } 1786 1787 //------------------------------------------------------------------------------ 1788 1789 void BWindow::Show(){ 1790 bool isLocked = this->IsLocked(); 1791 1792 fShowLevel--; 1793 1794 if (fShowLevel == 0){ 1795 STRACE(("BWindow(%s): sending AS_SHOW_WINDOW message...\n", Name() )); 1796 if ( !isLocked ) Lock(); 1797 top_view->Show(); 1798 session->WriteInt32( AS_SHOW_WINDOW ); 1799 session->Sync(); 1800 if ( !isLocked ) Unlock(); 1801 } 1802 1803 // if it's the fist time Show() is called... start the Looper thread. 1804 if ( Thread() == B_ERROR ) 1805 { 1806 // normaly this won't happen, but I want to be sure! 1807 if ( !isLocked ) Lock(); 1808 Run(); 1809 } 1810 1811 } 1812 1813 //------------------------------------------------------------------------------ 1814 1815 void BWindow::Hide(){ 1816 if (fShowLevel == 0){ 1817 Lock(); 1818 top_view->Hide(); 1819 session->WriteInt32( AS_HIDE_WINDOW ); 1820 session->Sync(); 1821 Unlock(); 1822 } 1823 fShowLevel++; 1824 } 1825 1826 //------------------------------------------------------------------------------ 1827 1828 bool BWindow::IsHidden() const{ 1829 return fShowLevel > 0; 1830 } 1831 1832 //------------------------------------------------------------------------------ 1833 1834 bool BWindow::QuitRequested(){ 1835 return BLooper::QuitRequested(); 1836 } 1837 1838 //------------------------------------------------------------------------------ 1839 1840 thread_id BWindow::Run(){ 1841 return BLooper::Run(); 1842 } 1843 1844 //------------------------------------------------------------------------------ 1845 1846 status_t BWindow::GetSupportedSuites(BMessage* data){ 1847 status_t err = B_OK; 1848 if (!data) 1849 err = B_BAD_VALUE; 1850 1851 if (!err){ 1852 err = data->AddString("Suites", "suite/vnd.Be-window"); 1853 if (!err){ 1854 BPropertyInfo propertyInfo(windowPropInfo); 1855 err = data->AddFlat("message", &propertyInfo); 1856 if (!err){ 1857 err = BLooper::GetSupportedSuites(data); 1858 } 1859 } 1860 } 1861 return err; 1862 } 1863 1864 //------------------------------------------------------------------------------ 1865 1866 BHandler* BWindow::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 1867 int32 what, const char* property) 1868 { 1869 if (msg->what == B_WINDOW_MOVE_BY) 1870 return this; 1871 if (msg->what == B_WINDOW_MOVE_TO) 1872 return this; 1873 1874 BPropertyInfo propertyInfo(windowPropInfo); 1875 switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) 1876 { 1877 case B_ERROR: 1878 break; 1879 case 0: 1880 case 1: 1881 case 2: 1882 case 3: 1883 case 4: 1884 case 5: 1885 case 6: 1886 case 7: 1887 case 8: 1888 case 9: 1889 case 10: 1890 case 11: 1891 case 12: 1892 case 13: 1893 return this; 1894 1895 case 14: 1896 if (fKeyMenuBar){ 1897 msg->PopSpecifier(); 1898 return fKeyMenuBar; 1899 } 1900 else{ 1901 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 1902 replyMsg.AddInt32( "error", B_NAME_NOT_FOUND ); 1903 replyMsg.AddString( "message", "This window doesn't have a main MenuBar"); 1904 msg->SendReply( &replyMsg ); 1905 return NULL; 1906 } 1907 case 15: 1908 // we will NOT pop the current specifier 1909 return top_view; 1910 1911 case 16: 1912 return this; 1913 } 1914 1915 return BLooper::ResolveSpecifier(msg, index, specifier, what, property); 1916 } 1917 1918 // PRIVATE 1919 //--------------------Private Methods------------------------------------------- 1920 // PRIVATE 1921 1922 void BWindow::InitData( BRect frame, 1923 const char* title, 1924 window_look look, 1925 window_feel feel, 1926 uint32 flags, 1927 uint32 workspace){ 1928 1929 STRACE(("BWindow::InitData(...)\n")); 1930 1931 fTitle=NULL; 1932 if ( be_app == NULL ){ 1933 debugger("You need a valid BApplication object before interacting with the app_server"); 1934 return; 1935 } 1936 1937 fFrame = frame; 1938 1939 if (title) 1940 SetTitle( title ); 1941 1942 fFeel = feel; 1943 fLook = look; 1944 fFlags = flags; 1945 1946 1947 fInTransaction = false; 1948 fActive = false; 1949 fShowLevel = 1; 1950 1951 top_view = NULL; 1952 fFocus = NULL; 1953 fLastMouseMovedView = NULL; 1954 fKeyMenuBar = NULL; 1955 fDefaultButton = NULL; 1956 1957 // accelList = new BList( 10 ); 1958 AddShortcut('X', B_COMMAND_KEY, new BMessage(B_CUT), NULL); 1959 AddShortcut('C', B_COMMAND_KEY, new BMessage(B_COPY), NULL); 1960 AddShortcut('V', B_COMMAND_KEY, new BMessage(B_PASTE), NULL); 1961 AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), NULL); 1962 AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 1963 1964 fPulseEnabled = false; 1965 fPulseRate = 0; 1966 fPulseRunner = NULL; 1967 1968 // TODO: is this correct??? should the thread loop be started??? 1969 //SetPulseRate( 500000 ); 1970 1971 // TODO: see if you can use 'fViewsNeedPulse' 1972 1973 fIsFilePanel = false; 1974 1975 // TODO: see WHEN is this used! 1976 fMaskActivated = false; 1977 1978 // TODO: see WHEN is this used! 1979 fWaitingForMenu = false; 1980 1981 fMinimized = false; 1982 1983 // TODO: see WHERE you can use 'fMenuSem' 1984 1985 fMaxZoomHeight = 32768.0; 1986 fMaxZoomWidth = 32768.0; 1987 fMinWindHeight = 0.0; 1988 fMinWindWidth = 0.0; 1989 fMaxWindHeight = 32768.0; 1990 fMaxWindWidth = 32768.0; 1991 1992 fLastViewToken = B_NULL_TOKEN; 1993 // TODO: other initializations! 1994 1995 /* 1996 Here, we will contact app_server and let him know that a window has 1997 been created 1998 */ 1999 receive_port = create_port( B_LOOPER_PORT_DEFAULT_CAPACITY , 2000 "w_rcv_port"); 2001 if (receive_port==B_BAD_VALUE || receive_port==B_NO_MORE_PORTS){ 2002 debugger("Could not create BWindow's receive port, used for interacting with the app_server!"); 2003 delete this; 2004 } 2005 2006 STRACE(("BWindow::InitData(): contacting app_server...\n")); 2007 // let app_server to know that a window has been created. 2008 2009 session = new BSession( receive_port, be_app->fServerFrom ); 2010 2011 // HERE we are in BApplication's thread, so for locking we use be_app variable 2012 // we'll lock the be_app to be sure we're the only one writing at BApplication's server port 2013 bool locked = false; 2014 if ( !(be_app->IsLocked()) ) 2015 { be_app->Lock(); locked = true; } 2016 2017 PortMessage pmsg; 2018 PortLink link(be_app->fServerFrom); 2019 link.SetOpCode(AS_CREATE_WINDOW); 2020 2021 link.Attach<BRect>( fFrame ); 2022 link.Attach<int32>( (int32)fLook ); 2023 link.Attach<int32>( (int32)fFeel ); 2024 link.Attach<uint32>( fFlags ); 2025 link.Attach<uint32>( workspace ); 2026 link.Attach<int32>( _get_object_token_(this) ); 2027 link.Attach<port_id>( receive_port ); 2028 link.Attach<port_id>( fMsgPort ); 2029 link.AttachString( title ); 2030 link.FlushWithReply(&pmsg); 2031 2032 pmsg.Read<port_id>(&send_port); 2033 2034 /* 2035 session->WriteInt32( AS_CREATE_WINDOW ); 2036 session->WriteRect( fFrame ); 2037 session->WriteInt32( (int32)fLook ); 2038 session->WriteInt32( (int32)fFeel ); 2039 session->WriteUInt32( fFlags ); 2040 session->WriteUInt32( workspace ); 2041 session->WriteData( &team, sizeof(team_id)); 2042 session->WriteInt32( _get_object_token_(this) ); 2043 session->WriteData( &receive_port, sizeof(port_id) ); 2044 session->WriteData( &fMsgPort, sizeof(port_id) ); 2045 session->WriteString( title ); 2046 2047 printf("look: %ld\n", (int32)fLook); 2048 printf("title: %s\n", title); 2049 session->Sync(); 2050 // The port on witch app_server will listen for us 2051 STRACE(("here\n")); 2052 session->ReadData( &send_port, sizeof(port_id) ); 2053 */ 2054 // unlock, so other threads can do their job. 2055 if( locked ) 2056 be_app->Unlock(); 2057 2058 session->SetSendPort(send_port); 2059 2060 STRACE(("\tapp_server link established.\n")); 2061 STRACE(("Window locked?: %s\n", IsLocked()?"True":"False")); 2062 2063 // build and register top_view with app_server 2064 BuildTopView(); 2065 // top_view->PrintToStream(); 2066 } 2067 2068 //------------------------------------------------------------------------------ 2069 2070 void BWindow::task_looper(){ 2071 2072 // Check that looper is locked (should be) 2073 AssertLocked(); 2074 2075 Unlock(); 2076 2077 using namespace BPrivate; 2078 bool dispatchNextMessage = false; 2079 BMessage *msg; 2080 2081 // loop: As long as we are not terminating. 2082 while (!fTerminating) 2083 { 2084 msg = MessageFromPort(); 2085 2086 // Did we get a message? 2087 if (msg){ 2088 // Add to queue 2089 fQueue->Lock(); 2090 fQueue->AddMessage(msg); 2091 fQueue->Unlock(); 2092 } 2093 2094 // Get message count from port 2095 int32 msgCount = port_count(fMsgPort); 2096 if (msgCount > 0){ 2097 fQueue->Lock(); 2098 for (int32 i = 0; i < msgCount; ++i) 2099 { 2100 // Read 'count' messages from port (so we will not block) 2101 // We use zero as our timeout since we know there is stuff there 2102 msg = MessageFromPort(0); 2103 // Add messages to queue 2104 if (msg) 2105 fQueue->AddMessage(msg); 2106 } 2107 fQueue->Unlock(); 2108 } 2109 2110 // loop: As long as there are messages in the queue and 2111 // and we are not terminating. 2112 dispatchNextMessage = true; 2113 while (!fTerminating && dispatchNextMessage) 2114 { 2115 fQueue->Lock(); 2116 fLastMessage = fQueue->NextMessage(); 2117 fQueue->Unlock(); 2118 2119 Lock(); 2120 2121 // TODO: add code for drag & drop 2122 if (!fLastMessage) 2123 { 2124 // No more messages: Unlock the looper and terminate the 2125 // dispatch loop. 2126 dispatchNextMessage = false; 2127 } 2128 else 2129 { 2130 // Get the target handler 2131 BHandler* handler; 2132 if (_use_preferred_target_(fLastMessage)) 2133 handler = fPreferred; 2134 else 2135 gDefaultTokens.GetToken(_get_message_target_(fLastMessage), 2136 B_HANDLER_TOKEN, 2137 (void**)&handler); 2138 2139 if (!handler) 2140 handler = this; 2141 2142 // Is this a scripting message? 2143 if (fLastMessage->HasSpecifiers()) 2144 { 2145 int32 index = 0; 2146 // Make sure the current specifier is kosher 2147 if (fLastMessage->GetCurrentSpecifier(&index) == B_OK) 2148 handler = resolve_specifier(handler, fLastMessage); 2149 } 2150 2151 if (handler) 2152 { 2153 // Do filtering 2154 handler = top_level_filter(fLastMessage, handler); 2155 if (handler && handler->Looper() == this) 2156 DispatchMessage(fLastMessage, handler); 2157 } 2158 } 2159 // empty our message buffer 2160 session->Sync(); 2161 2162 Unlock(); 2163 printf("Lock released\n"); 2164 // Delete the current message (fLastMessage) 2165 if (fLastMessage) 2166 { 2167 delete fLastMessage; 2168 fLastMessage = NULL; 2169 } 2170 2171 // Are any messages on the port? 2172 if (port_count(fMsgPort) > 0) 2173 { 2174 // Do outer loop 2175 dispatchNextMessage = false; 2176 } 2177 } 2178 } 2179 2180 } 2181 2182 //------------------------------------------------------------------------------ 2183 2184 BMessage* BWindow::ReadMessageFromPort(bigtime_t tout){ 2185 // TODO: remove! 2186 } 2187 2188 //------------------------------------------------------------------------------ 2189 2190 window_type BWindow::composeType(window_look look, 2191 window_feel feel) const 2192 { 2193 window_type returnValue = B_UNTYPED_WINDOW; 2194 2195 switch(feel) 2196 { 2197 case B_NORMAL_WINDOW_FEEL: 2198 switch (look) 2199 { 2200 case B_TITLED_WINDOW_LOOK: 2201 returnValue = B_TITLED_WINDOW; 2202 break; 2203 2204 case B_DOCUMENT_WINDOW_LOOK: 2205 returnValue = B_DOCUMENT_WINDOW; 2206 break; 2207 2208 case B_BORDERED_WINDOW_LOOK: 2209 returnValue = B_BORDERED_WINDOW; 2210 break; 2211 2212 default: 2213 returnValue = B_UNTYPED_WINDOW; 2214 } 2215 break; 2216 2217 case B_MODAL_APP_WINDOW_FEEL: 2218 if (look == B_MODAL_WINDOW_LOOK) 2219 returnValue = B_MODAL_WINDOW; 2220 break; 2221 2222 case B_FLOATING_APP_WINDOW_FEEL: 2223 if (look == B_FLOATING_WINDOW_LOOK) 2224 returnValue = B_FLOATING_WINDOW; 2225 break; 2226 2227 default: 2228 returnValue = B_UNTYPED_WINDOW; 2229 } 2230 2231 return returnValue; 2232 } 2233 2234 //------------------------------------------------------------------------------ 2235 2236 void BWindow::decomposeType(window_type type, 2237 window_look* look, 2238 window_feel* feel) const 2239 { 2240 switch (type) 2241 { 2242 case B_TITLED_WINDOW: 2243 *look = B_TITLED_WINDOW_LOOK; 2244 *feel = B_NORMAL_WINDOW_FEEL; 2245 break; 2246 case B_DOCUMENT_WINDOW: 2247 *look = B_DOCUMENT_WINDOW_LOOK; 2248 *feel = B_NORMAL_WINDOW_FEEL; 2249 break; 2250 case B_MODAL_WINDOW: 2251 *look = B_MODAL_WINDOW_LOOK; 2252 *feel = B_MODAL_APP_WINDOW_FEEL; 2253 break; 2254 case B_FLOATING_WINDOW: 2255 *look = B_FLOATING_WINDOW_LOOK; 2256 *feel = B_FLOATING_APP_WINDOW_FEEL; 2257 break; 2258 case B_BORDERED_WINDOW: 2259 *look = B_BORDERED_WINDOW_LOOK; 2260 *feel = B_NORMAL_WINDOW_FEEL; 2261 break; 2262 case B_UNTYPED_WINDOW: 2263 *look = B_TITLED_WINDOW_LOOK; 2264 *feel = B_NORMAL_WINDOW_FEEL; 2265 break; 2266 default: 2267 *look = B_TITLED_WINDOW_LOOK; 2268 *feel = B_NORMAL_WINDOW_FEEL; 2269 break; 2270 } 2271 } 2272 2273 //------------------------------------------------------------------------------ 2274 2275 void BWindow::BuildTopView(){ 2276 2277 top_view = new BView( fFrame, "top_view", 2278 B_FOLLOW_ALL, B_WILL_DRAW); 2279 top_view->top_level_view = true; 2280 top_view->fShowLevel = 1; 2281 2282 // set top_view's owner, add it to window's eligible handler list 2283 // and also set its next handler to this window. 2284 top_view->setOwner( this ); 2285 2286 // send top_view's information to app_server 2287 session->WriteInt32( AS_LAYER_CREATE_ROOT ); 2288 fLastViewToken = _get_object_token_( top_view ); 2289 2290 top_view->attachView(top_view); 2291 2292 STRACE(("BuildTopView ended\n")); 2293 } 2294 2295 //------------------------------------------------------------------------------ 2296 2297 void BWindow::stopConnection(){ 2298 Lock(); 2299 session->WriteInt32( B_QUIT_REQUESTED ); 2300 session->Sync(); 2301 Unlock(); 2302 } 2303 2304 //------------------------------------------------------------------------------ 2305 2306 void BWindow::prepareView(BView *aView){ 2307 2308 // TODO: implement 2309 2310 } 2311 2312 //------------------------------------------------------------------------------ 2313 2314 void BWindow::attachView(BView *aView){ 2315 2316 // TODO: implement 2317 2318 } 2319 2320 //------------------------------------------------------------------------------ 2321 2322 void BWindow::detachView(BView *aView){ 2323 2324 // TODO: implement 2325 2326 } 2327 //------------------------------------------------------------------------------ 2328 2329 void BWindow::setFocus(BView *focusView, bool notifyInputServer){ 2330 BView* previousFocus = fFocus; 2331 2332 if (previousFocus == focusView) 2333 return; 2334 2335 fFocus = NULL; 2336 2337 if (previousFocus != NULL) 2338 previousFocus->Invalidate(); 2339 2340 fFocus = focusView; 2341 2342 if (focusView != NULL) 2343 focusView->Invalidate(); 2344 2345 // TODO: find out why do we have to notify input server. 2346 if (notifyInputServer){ 2347 // what am I suppose to do here?? 2348 } 2349 } 2350 2351 //------------------------------------------------------------------------------ 2352 2353 void BWindow::handleActivation( bool active ){ 2354 2355 if (active){ 2356 // TODO: talk to Ingo to make BWindow a friend for BRoster 2357 // be_roster->UpdateActiveApp( be_app->Team() ); 2358 } 2359 2360 WindowActivated( active ); 2361 2362 // recursively call hook function 'WindowActivated(bool)' 2363 // for all views attached to this window. 2364 activateView( top_view, active ); 2365 } 2366 2367 //------------------------------------------------------------------------------ 2368 2369 void BWindow::activateView( BView *aView, bool active ){ 2370 2371 aView->WindowActivated( active ); 2372 2373 BView *child; 2374 if ( (child = aView->first_child) ){ 2375 while ( child ) { 2376 activateView( child, active ); 2377 child = child->next_sibling; 2378 } 2379 } 2380 } 2381 2382 //------------------------------------------------------------------------------ 2383 2384 bool BWindow::handleKeyDown( int32 raw_char, uint32 modifiers){ 2385 2386 // TODO: ask people if using 'raw_char' is OK ? 2387 2388 // handle BMenuBar key 2389 if ( (raw_char == B_ESCAPE) && (modifiers & B_COMMAND_KEY) 2390 && fKeyMenuBar) 2391 { 2392 2393 // TODO: ask Marc about 'fWaitingForMenu' member! 2394 2395 // fWaitingForMenu = true; 2396 fKeyMenuBar->StartMenuBar(0, true, false, NULL); 2397 return true; 2398 } 2399 2400 // Command+q has been pressed, so, we will quit 2401 if ( (raw_char == 'Q' || raw_char == 'q') && modifiers & B_COMMAND_KEY){ 2402 be_app->PostMessage(B_QUIT_REQUESTED); 2403 return true; 2404 } 2405 2406 // Keyboard navigation through views!!!! 2407 if ( raw_char == B_TAB){ 2408 2409 // even if we have no focus view, we'll say that we will handle TAB key 2410 if (!fFocus) 2411 return true; 2412 2413 BView *nextFocus; 2414 2415 if (modifiers & B_CONTROL_KEY & B_SHIFT_KEY){ 2416 nextFocus = findPrevView( fFocus, B_NAVIGABLE_JUMP ); 2417 } 2418 else 2419 if (modifiers & B_CONTROL_KEY){ 2420 nextFocus = findNextView( fFocus, B_NAVIGABLE_JUMP ); 2421 } 2422 else 2423 if (modifiers & B_SHIFT_KEY){ 2424 nextFocus = findPrevView( fFocus, B_NAVIGABLE ); 2425 } 2426 else 2427 nextFocus = findNextView( fFocus, B_NAVIGABLE ); 2428 2429 if ( nextFocus ) 2430 setFocus( nextFocus, false ); 2431 2432 return true; 2433 } 2434 2435 // Handle shortcuts 2436 int index; 2437 if ( (index = findShortcut(raw_char, modifiers)) >=0){ 2438 _BCmdKey *cmdKey; 2439 2440 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 2441 2442 // we'll give the message to the focus view 2443 if (cmdKey->targetToken == B_ANY_TOKEN){ 2444 fFocus->MessageReceived( cmdKey->message ); 2445 return true; 2446 } 2447 else{ 2448 BHandler *handler; 2449 BHandler *aHandler; 2450 int noOfHandlers; 2451 2452 // search for a match through BLooper's list of eligible handlers 2453 handler = NULL; 2454 noOfHandlers = CountHandlers(); 2455 for( int i=0; i < noOfHandlers; i++ ) 2456 // do we have a match? 2457 if ( _get_object_token_( aHandler = HandlerAt(i) ) 2458 == cmdKey->targetToken) 2459 { 2460 // yes, we do. 2461 handler = aHandler; 2462 break; 2463 } 2464 2465 if ( handler ) 2466 handler->MessageReceived( cmdKey->message ); 2467 else 2468 // if no handler was found, BWindow will handle the message 2469 MessageReceived( cmdKey->message ); 2470 } 2471 return true; 2472 } 2473 2474 // if <ENTER> is pressed and we have a default button 2475 if (DefaultButton() && (raw_char == B_ENTER)){ 2476 const char *chars; // just to be sure 2477 CurrentMessage()->FindString("bytes", &chars); 2478 2479 DefaultButton()->KeyDown( chars, strlen(chars)-1 ); 2480 return true; 2481 } 2482 2483 2484 return false; 2485 } 2486 2487 //------------------------------------------------------------------------------ 2488 2489 BView* BWindow::sendMessageUsingEventMask2( BView* aView, int32 message, BPoint where ){ 2490 2491 BView *destView; 2492 destView = NULL; 2493 2494 if ( aView->fBounds.Contains( aView->ConvertFromScreen(where) ) && 2495 !aView->first_child ){ 2496 return aView; 2497 } 2498 2499 // Code for Event Masks 2500 BView *child; 2501 if ( (child = aView->first_child) ){ 2502 while ( child ) { 2503 // see if a BView registered for mouse events and it's not the current focus view 2504 if ( child->fEventMask & B_POINTER_EVENTS && 2505 aView != fFocus ){ 2506 switch (message){ 2507 case B_MOUSE_DOWN:{ 2508 child->MouseDown( child->ConvertFromScreen( where ) ); 2509 } 2510 break; 2511 2512 case B_MOUSE_UP:{ 2513 child->MouseUp( child->ConvertFromScreen( where ) ); 2514 } 2515 break; 2516 2517 case B_MOUSE_MOVED:{ 2518 BMessage *dragMessage; 2519 2520 // TODO: get the dragMessage if any 2521 // for now... 2522 dragMessage = NULL; 2523 2524 /* TODO: after you have an example working, see if a view that registered for such events, 2525 does reveive B_MOUSE_MOVED with other options than B_OUTDIDE_VIEW !!! 2526 like: B_INSIDE_VIEW, B_ENTERED_VIEW, B_EXITED_VIEW 2527 */ 2528 child->MouseMoved( ConvertFromScreen(where), B_OUTSIDE_VIEW , dragMessage); 2529 } 2530 break; 2531 } 2532 } 2533 if (destView == NULL) 2534 destView = sendMessageUsingEventMask2( child, message, where ); 2535 else 2536 sendMessageUsingEventMask2( child, message, where ); 2537 child = child->next_sibling; 2538 } 2539 } 2540 2541 return destView; 2542 } 2543 2544 //------------------------------------------------------------------------------ 2545 2546 void BWindow::sendMessageUsingEventMask( int32 message, BPoint where ){ 2547 BView* destView; 2548 2549 destView = sendMessageUsingEventMask2(top_view, message, where); 2550 2551 // I'm SURE this is NEVER going to happen, but, durring development of BWindow, it may slip a NULL value 2552 if (!destView){ 2553 // debugger("There is no BView under the mouse;"); 2554 return; 2555 } 2556 2557 switch( message ){ 2558 case B_MOUSE_DOWN:{ 2559 setFocus( destView ); 2560 destView->MouseDown( destView->ConvertFromScreen( where ) ); 2561 break;} 2562 2563 case B_MOUSE_UP:{ 2564 destView->MouseUp( destView->ConvertFromScreen( where ) ); 2565 break;} 2566 2567 case B_MOUSE_MOVED:{ 2568 BMessage *dragMessage; 2569 2570 // TODO: add code for drag and drop 2571 // for now... 2572 dragMessage = NULL; 2573 2574 if (destView != fLastMouseMovedView){ 2575 fLastMouseMovedView->MouseMoved( destView->ConvertFromScreen( where ), B_EXITED_VIEW , dragMessage); 2576 destView->MouseMoved( ConvertFromScreen( where ), B_ENTERED_VIEW, dragMessage); 2577 fLastMouseMovedView = destView; 2578 } 2579 else{ 2580 destView->MouseMoved( ConvertFromScreen( where ), B_INSIDE_VIEW , dragMessage); 2581 } 2582 2583 // I'm guessing that B_OUTSIDE_VIEW is given to the view that has focus, I'll have to check 2584 // TODO: Do a research on mouse capturing, maybe it has something to do with this 2585 if (fFocus != destView) 2586 fFocus->MouseMoved( ConvertFromScreen( where ), B_OUTSIDE_VIEW , dragMessage); 2587 break;} 2588 } 2589 } 2590 2591 //------------------------------------------------------------------------------ 2592 2593 BMessage* BWindow::ConvertToMessage(void* raw1, int32 code){ 2594 2595 BMessage *msg; 2596 msg = new BMessage(); 2597 // time since 01/01/70 2598 int64 when; 2599 2600 switch(code){ 2601 case B_WINDOW_ACTIVATED:{ 2602 bool active; 2603 2604 session->ReadInt64( &when ); 2605 session->ReadBool( &active ); 2606 2607 msg->what = B_WINDOW_ACTIVATED; 2608 msg->AddInt64("when", when); 2609 msg->AddBool("active", active); 2610 2611 break;} 2612 2613 case B_QUIT_REQUESTED:{ 2614 2615 msg->what = B_QUIT_REQUESTED; 2616 msg->AddBool("shortcut", false); 2617 2618 break;} 2619 2620 case B_KEY_DOWN:{ 2621 int32 physicalKeyCode, 2622 repeat, 2623 modifiers, 2624 ASCIIcode; 2625 char *bytes = NULL; 2626 uint8 states; 2627 int8 UTF8_1, UTF8_2, UTF8_3; 2628 2629 session->ReadInt64( &when ); 2630 session->ReadInt32( &physicalKeyCode ); 2631 session->ReadInt32( &repeat ); 2632 session->ReadInt32( &modifiers ); 2633 session->ReadUInt8( &states ); 2634 session->ReadInt8( &UTF8_1 ); 2635 session->ReadInt8( &UTF8_2 ); 2636 session->ReadInt8( &UTF8_3 ); 2637 session->ReadInt32( &ASCIIcode ); 2638 bytes = session->ReadString(); 2639 2640 msg->what = B_KEY_DOWN; 2641 msg->AddInt64("when", when); 2642 msg->AddInt32("key", physicalKeyCode); 2643 msg->AddInt32("be:key_repeat", repeat); 2644 msg->AddInt32("modifiers", modifiers); 2645 msg->AddInt8("states", states); 2646 msg->AddInt8("byte", UTF8_1); 2647 msg->AddInt8("byte", UTF8_2); 2648 msg->AddInt8("byte", UTF8_3); 2649 msg->AddInt32("raw_char", ASCIIcode); 2650 msg->AddString("bytes", bytes); 2651 2652 if (bytes) 2653 delete bytes; 2654 2655 break;} 2656 2657 case B_KEY_UP:{ 2658 int32 physicalKeyCode, 2659 modifiers, 2660 ASCIIcode; 2661 char *bytes; 2662 uint8 states; 2663 int8 UTF8_1, UTF8_2, UTF8_3; 2664 2665 session->ReadInt64( &when ); 2666 session->ReadInt32( &physicalKeyCode ); 2667 session->ReadInt32( &modifiers ); 2668 session->ReadUInt8( &states ); 2669 session->ReadInt8( &UTF8_1 ); 2670 session->ReadInt8( &UTF8_2 ); 2671 session->ReadInt8( &UTF8_3 ); 2672 session->ReadInt32( &ASCIIcode ); 2673 bytes = session->ReadString(); 2674 2675 msg->what = B_KEY_UP; 2676 msg->AddInt64("when", when); 2677 msg->AddInt32("key", physicalKeyCode); 2678 msg->AddInt32("modifiers", modifiers); 2679 msg->AddInt8("states", states); 2680 msg->AddInt8("byte", UTF8_1); 2681 msg->AddInt8("byte", UTF8_2); 2682 msg->AddInt8("byte", UTF8_3); 2683 msg->AddInt32("raw_char", ASCIIcode); 2684 msg->AddString("bytes", bytes); 2685 2686 if (bytes) 2687 delete bytes; 2688 2689 break;} 2690 2691 case B_UNMAPPED_KEY_DOWN:{ 2692 int32 physicalKeyCode, 2693 modifiers; 2694 uint8 states; 2695 2696 session->ReadInt64( &when ); 2697 session->ReadInt32( &physicalKeyCode ); 2698 session->ReadInt32( &modifiers ); 2699 session->ReadUInt8( &states ); 2700 2701 msg->what = B_UNMAPPED_KEY_DOWN; 2702 msg->AddInt64("when", when); 2703 msg->AddInt32("key", physicalKeyCode); 2704 msg->AddInt32("modifiers", modifiers); 2705 msg->AddInt8("states", states); 2706 2707 break;} 2708 2709 case B_UNMAPPED_KEY_UP:{ 2710 int32 physicalKeyCode, 2711 modifiers; 2712 uint8 states; 2713 2714 session->ReadInt64( &when ); 2715 session->ReadInt32( &physicalKeyCode ); 2716 session->ReadInt32( &modifiers ); 2717 session->ReadUInt8( &states ); 2718 2719 msg->what = B_UNMAPPED_KEY_UP; 2720 msg->AddInt64("when", when); 2721 msg->AddInt32("key", physicalKeyCode); 2722 msg->AddInt32("modifiers", modifiers); 2723 msg->AddInt8("states", states); 2724 2725 break;} 2726 2727 case B_MODIFIERS_CHANGED:{ 2728 int32 modifiers, 2729 modifiersOld; 2730 uint8 states; 2731 2732 session->ReadInt64( &when ); 2733 session->ReadInt32( &modifiers ); 2734 session->ReadInt32( &modifiersOld ); 2735 session->ReadUInt8( &states ); 2736 2737 msg->what = B_MODIFIERS_CHANGED; 2738 msg->AddInt64("when", when); 2739 msg->AddInt32("modifiers", modifiers); 2740 msg->AddInt32("be:old_modifiers", modifiersOld); 2741 msg->AddInt8("states", states); 2742 2743 break;} 2744 2745 case B_MINIMIZE:{ 2746 bool minimize; 2747 2748 session->ReadInt64( &when ); 2749 session->ReadBool( &minimize ); 2750 2751 msg->what = B_MINIMIZE; 2752 msg->AddInt64("when", when); 2753 msg->AddBool("minimize", minimize); 2754 2755 break;} 2756 2757 case B_MOUSE_DOWN:{ 2758 int32 modifiers, 2759 buttons, 2760 noOfClicks; 2761 BPoint where; 2762 2763 session->ReadInt64( &when ); 2764 session->ReadPoint( &where ); 2765 session->ReadInt32( &modifiers ); 2766 session->ReadInt32( &buttons ); 2767 session->ReadInt32( &noOfClicks ); 2768 2769 msg->what = B_MOUSE_DOWN; 2770 msg->AddInt64("when", when); 2771 msg->AddPoint("where", where); 2772 msg->AddInt32("modifiers", modifiers); 2773 msg->AddInt32("buttons", buttons); 2774 msg->AddInt32("clicks", noOfClicks); 2775 2776 break;} 2777 2778 case B_MOUSE_MOVED:{ 2779 int32 buttons; 2780 int32 modifiers; // added by OBOS Team 2781 BPoint where; 2782 2783 session->ReadInt64( &when ); 2784 session->ReadPoint( &where ); 2785 session->ReadInt32( &buttons ); 2786 session->ReadInt32( &modifiers ); 2787 2788 msg->what = B_MOUSE_MOVED; 2789 msg->AddInt64("when", when); 2790 msg->AddPoint("where", where); 2791 msg->AddInt32("buttons", buttons); 2792 msg->AddInt32("modifiers", modifiers); 2793 2794 break;} 2795 2796 case B_MOUSE_UP:{ 2797 int32 modifiers, 2798 buttons; 2799 BPoint where; 2800 2801 session->ReadInt64( &when ); 2802 session->ReadPoint( &where ); 2803 session->ReadInt32( &buttons ); 2804 session->ReadInt32( &modifiers ); 2805 2806 msg->what = B_MOUSE_UP; 2807 msg->AddInt64("when", when); 2808 msg->AddPoint("where", where); 2809 msg->AddInt32("modifiers", modifiers); 2810 msg->AddInt32("buttons", buttons); 2811 2812 break;} 2813 2814 case B_MOUSE_WHEEL_CHANGED:{ 2815 float whellChangeX, 2816 whellChangeY; 2817 2818 session->ReadInt64( &when ); 2819 session->ReadFloat( &whellChangeX ); 2820 session->ReadFloat( &whellChangeY ); 2821 2822 msg->what = B_MOUSE_WHEEL_CHANGED; 2823 msg->AddInt64("when", when); 2824 msg->AddFloat("be:wheel_delta_x", whellChangeX); 2825 msg->AddFloat("be:wheel_delta_y", whellChangeY); 2826 2827 break;} 2828 2829 case B_SCREEN_CHANGED:{ 2830 int32 colorSpace; 2831 BRect frame; 2832 2833 session->ReadInt64( &when ); 2834 session->ReadRect( &frame ); 2835 session->ReadInt32( &colorSpace ); 2836 2837 msg->what = B_SCREEN_CHANGED; 2838 msg->AddInt64("when", when); 2839 msg->AddRect("frame", frame); 2840 msg->AddInt32("mode", colorSpace); 2841 2842 break;} 2843 2844 case B_WINDOW_MOVED:{ 2845 BPoint where; 2846 2847 session->ReadInt64( &when ); 2848 session->ReadPoint( &where ); 2849 2850 msg->what = B_WINDOW_MOVED; 2851 msg->AddInt64("when", when); 2852 msg->AddPoint("where", where); 2853 2854 break;} 2855 2856 case B_WINDOW_RESIZED:{ 2857 int32 newWidth, 2858 newHeight; 2859 2860 session->ReadInt64( &when ); 2861 session->ReadInt32( &newWidth ); 2862 session->ReadInt32( &newHeight ); 2863 2864 msg->what = B_WINDOW_RESIZED; 2865 msg->AddInt64("when", when); 2866 msg->AddInt32("width", newWidth); 2867 msg->AddInt32("height", newHeight); 2868 2869 break;} 2870 2871 case B_WORKSPACES_CHANGED:{ 2872 int32 newWorkSpace, 2873 oldWorkSpace; 2874 2875 session->ReadInt64( &when ); 2876 session->ReadInt32( &newWorkSpace ); 2877 session->ReadInt32( &oldWorkSpace ); 2878 2879 msg->what = B_WORKSPACES_CHANGED; 2880 msg->AddInt64("when", when); 2881 msg->AddInt32("old", oldWorkSpace); 2882 msg->AddInt32("new", newWorkSpace); 2883 2884 break;} 2885 2886 case B_WORKSPACE_ACTIVATED:{ 2887 int32 workSpace; 2888 bool active; 2889 2890 session->ReadInt64( &when ); 2891 session->ReadInt32( &workSpace ); 2892 session->ReadBool( &active ); 2893 2894 msg->what = B_WORKSPACE_ACTIVATED; 2895 msg->AddInt64("when", when); 2896 msg->AddInt32("workspace", workSpace); 2897 msg->AddBool("active", active); 2898 2899 break;} 2900 2901 case B_ZOOM:{ 2902 2903 session->ReadInt64( &when ); 2904 2905 msg->what = B_ZOOM; 2906 msg->AddInt64("when", when); 2907 2908 break;} 2909 2910 default:{ 2911 delete msg; 2912 2913 msg = BLooper::ConvertToMessage( raw1, code ); 2914 if (!msg) 2915 printf("***PANIC: app_server message NOT understood: '%c%c%c%c'***\n", 2916 (char)((code & 0xFF000000) >> 24), (char)((code & 0x00FF0000) >> 16), 2917 (char)((code & 0x0000FF00) >> 8), (char)(code & 0x000000FF) ); 2918 } 2919 } 2920 2921 return msg; 2922 } 2923 2924 //------------------------------------------------------------------------------ 2925 2926 void BWindow::sendPulse( BView* aView ){ 2927 BView *child; 2928 if ( (child = aView->first_child) ){ 2929 while ( child ) { 2930 if ( child->Flags() & B_PULSE_NEEDED ) child->Pulse(); 2931 sendPulse( child ); 2932 child = child->next_sibling; 2933 } 2934 } 2935 } 2936 2937 //------------------------------------------------------------------------------ 2938 2939 int32 BWindow::findShortcut( uint32 key, uint32 modifiers ){ 2940 int32 index, 2941 noOfItems; 2942 2943 index = -1; 2944 noOfItems = accelList.CountItems(); 2945 2946 for ( int32 i = 0; i < noOfItems; i++ ) { 2947 _BCmdKey* tempCmdKey; 2948 2949 tempCmdKey = (_BCmdKey*)accelList.ItemAt(i); 2950 if (tempCmdKey->key == key && tempCmdKey->modifiers == modifiers){ 2951 index = i; 2952 break; 2953 } 2954 } 2955 2956 return index; 2957 } 2958 2959 //------------------------------------------------------------------------------ 2960 2961 BView* BWindow::findView(BView* aView, int32 token){ 2962 2963 if ( _get_object_token_(aView) == token ) 2964 return aView; 2965 2966 BView *child; 2967 if ( (child = aView->first_child) ){ 2968 while ( child ) { 2969 BView* view; 2970 if ( (view = findView( child, token )) ) 2971 return view; 2972 child = child->next_sibling; 2973 } 2974 } 2975 2976 return NULL; 2977 } 2978 2979 //------------------------------------------------------------------------------ 2980 2981 BView* BWindow::findView(BView* aView, const char* viewName) const{ 2982 2983 if ( strcmp( viewName, aView->Name() ) == 0) 2984 return aView; 2985 2986 BView *child; 2987 if ( (child = aView->first_child) ){ 2988 while ( child ) { 2989 BView* view; 2990 if ( (view = findView( child, viewName )) ) 2991 return view; 2992 child = child->next_sibling; 2993 } 2994 } 2995 2996 return NULL; 2997 } 2998 2999 //------------------------------------------------------------------------------ 3000 3001 BView* BWindow::findView(BView* aView, BPoint point) const{ 3002 3003 if ( aView->Bounds().Contains(point) && 3004 !aView->first_child ) 3005 return aView; 3006 3007 BView *child; 3008 if ( (child = aView->first_child) ){ 3009 while ( child ) { 3010 BView* view; 3011 if ( (view = findView( child, point )) ) 3012 return view; 3013 child = child->next_sibling; 3014 } 3015 } 3016 3017 return NULL; 3018 } 3019 3020 //------------------------------------------------------------------------------ 3021 3022 BView* BWindow::findNextView( BView *focus, uint32 flags){ 3023 bool found; 3024 found = false; 3025 3026 BView *nextFocus; 3027 nextFocus = focus; 3028 3029 /* Ufff... this toked me some time... this is the best form I've reached. 3030 This algorithm searches the tree for BViews that accept focus. 3031 */ 3032 while (!found){ 3033 if (nextFocus->first_child) 3034 nextFocus = nextFocus->first_child; 3035 else 3036 if (nextFocus->next_sibling) 3037 nextFocus = nextFocus->next_sibling; 3038 else{ 3039 while( !nextFocus->next_sibling && nextFocus->parent ){ 3040 nextFocus = nextFocus->parent; 3041 } 3042 3043 if (nextFocus == top_view) 3044 nextFocus = nextFocus->first_child; 3045 else 3046 nextFocus = nextFocus->next_sibling; 3047 } 3048 3049 if (nextFocus->Flags() & flags) 3050 found = true; 3051 3052 /* It means that the hole tree has been searched and there is no 3053 view with B_NAVIGABLE_JUMP flag set! 3054 */ 3055 if (nextFocus == focus) 3056 return NULL; 3057 } 3058 3059 return nextFocus; 3060 } 3061 3062 //------------------------------------------------------------------------------ 3063 3064 BView* BWindow::findPrevView( BView *focus, uint32 flags){ 3065 bool found; 3066 found = false; 3067 3068 BView *prevFocus; 3069 prevFocus = focus; 3070 3071 BView *aView; 3072 3073 while (!found){ 3074 if ( (aView = findLastChild(prevFocus)) ) 3075 prevFocus = aView; 3076 else 3077 if (prevFocus->prev_sibling) 3078 prevFocus = prevFocus->prev_sibling; 3079 else{ 3080 while( !prevFocus->prev_sibling && prevFocus->parent ){ 3081 prevFocus = prevFocus->parent; 3082 } 3083 3084 if (prevFocus == top_view) 3085 prevFocus = findLastChild( prevFocus ); 3086 else 3087 prevFocus = prevFocus->prev_sibling; 3088 } 3089 3090 if (prevFocus->Flags() & flags) 3091 found = true; 3092 3093 3094 /* It means that the hole tree has been searched and there is no 3095 view with B_NAVIGABLE_JUMP flag set! 3096 */ 3097 if (prevFocus == focus) 3098 return NULL; 3099 } 3100 3101 return prevFocus; 3102 } 3103 3104 //------------------------------------------------------------------------------ 3105 3106 BView* BWindow::findLastChild(BView *parent){ 3107 BView *aView; 3108 if ( (aView = parent->first_child) ){ 3109 while (aView->next_sibling) 3110 aView = aView->next_sibling; 3111 3112 return aView; 3113 } 3114 else 3115 return NULL; 3116 } 3117 3118 //------------------------------------------------------------------------------ 3119 3120 void BWindow::drawAllViews(BView* aView){ 3121 3122 BMessageQueue *queue; 3123 BMessage *msg; 3124 3125 queue = MessageQueue(); 3126 3127 // process all update BMessages from message queue 3128 queue->Lock(); 3129 while ( (msg = queue->FindMessage( (uint32)_UPDATE_ )) ) 3130 { 3131 Lock(); 3132 DispatchMessage( msg, this ); 3133 Unlock(); 3134 3135 queue->RemoveMessage( msg ); 3136 } 3137 queue->Unlock(); 3138 3139 // we'll send a message to app_server, tell him that we want all our views updated 3140 Lock(); 3141 session->WriteInt32( AS_UPDATE_IF_NEEDED ); 3142 session->Sync(); 3143 Unlock(); 3144 3145 // TODO: update!!!!!!!!!!!!!!!!!!! 3146 // process all update messages from receive port queue 3147 bool over = false; 3148 while (!over) 3149 { 3150 msg = MessageFromPort(0); 3151 if (msg){ 3152 switch (msg->what){ 3153 3154 case _ALL_UPDATED_:{ 3155 over = true; 3156 }break; 3157 3158 case _UPDATE_:{ 3159 Lock(); 3160 DispatchMessage( msg, this ); 3161 Unlock(); 3162 }break; 3163 3164 default:{ 3165 queue->Lock(); 3166 queue->AddMessage(msg); 3167 queue->Unlock(); 3168 }break; 3169 } 3170 } 3171 } 3172 } 3173 3174 //------------------------------------------------------------------------------ 3175 3176 void BWindow::drawView(BView* aView, BRect area){ 3177 3178 /* TODO: Drawing during an Update 3179 These settings are temporary. When the update is over, all graphics 3180 parameters are reset to their initial values 3181 */ 3182 aView->Draw( area ); 3183 3184 BView *child; 3185 if ( (child = aView->first_child) ){ 3186 while ( child ) { 3187 if ( area.Intersects( child->Frame() ) ){ 3188 BRect newArea; 3189 3190 newArea = area & child->Frame(); 3191 child->ConvertFromParent( &newArea ); 3192 child->Invalidate( newArea ); 3193 } 3194 child = child->next_sibling; 3195 } 3196 } 3197 } 3198 3199 //------------------------------------------------------------------------------ 3200 3201 void BWindow::SetIsFilePanel(bool yes){ 3202 3203 // TODO: is this not enough? 3204 fIsFilePanel = yes; 3205 } 3206 3207 //------------------------------------------------------------------------------ 3208 3209 bool BWindow::IsFilePanel() const{ 3210 return fIsFilePanel; 3211 } 3212 3213 3214 //------------------------------------------------------------------------------ 3215 // Virtual reserved Functions 3216 3217 void BWindow::_ReservedWindow1() { } 3218 //------------------------------------------------------------------------------ 3219 void BWindow::_ReservedWindow2() { } 3220 //------------------------------------------------------------------------------ 3221 void BWindow::_ReservedWindow3() { } 3222 //------------------------------------------------------------------------------ 3223 void BWindow::_ReservedWindow4() { } 3224 //------------------------------------------------------------------------------ 3225 void BWindow::_ReservedWindow5() { } 3226 //------------------------------------------------------------------------------ 3227 void BWindow::_ReservedWindow6() { } 3228 //------------------------------------------------------------------------------ 3229 void BWindow::_ReservedWindow7() { } 3230 //------------------------------------------------------------------------------ 3231 void BWindow::_ReservedWindow8() { } 3232 3233 void BWindow::PrintToStream() const{ 3234 printf("BWindow '%s' data:\ 3235 Title = %s\ 3236 Token = %ld\ 3237 InTransaction = %s\ 3238 Active = %s\ 3239 fShowLevel = %d\ 3240 Flags = %lx\ 3241 send_port = %ld\ 3242 receive_port = %ld\ 3243 top_view name = %s\ 3244 focus view name = %s\ 3245 lastMouseMoved = %s\ 3246 session = %s\ 3247 KeyMenuBar name = %s\ 3248 DefaultButton = %s\ 3249 # of shortcuts = %ld", 3250 Name(), 3251 fTitle!=NULL? fTitle:"NULL", 3252 _get_object_token_(this), 3253 fInTransaction==true? "yes":"no", 3254 fActive==true? "yes":"no", 3255 fShowLevel, 3256 fFlags, 3257 send_port, 3258 receive_port, 3259 top_view!=NULL? top_view->Name():"NULL", 3260 fFocus!=NULL? fFocus->Name():"NULL", 3261 fLastMouseMovedView!=NULL? fLastMouseMovedView->Name():"NULL", 3262 session!=NULL? "In place":"NULL", 3263 fKeyMenuBar!=NULL? fKeyMenuBar->Name():"NULL", 3264 fDefaultButton!=NULL? fDefaultButton->Name():"NULL", 3265 accelList.CountItems()); 3266 /* 3267 for( int32 i=0; i<accelList.CountItems(); i++){ 3268 _BCmdKey *key = (_BCmdKey*)accelList.ItemAt(i); 3269 printf("\tShortCut %ld: char %s\n\t\t message: \n", i, (key->key > 127)?"ASCII":"UNICODE"); 3270 key->message->PrintToStream(); 3271 } 3272 */ 3273 printf("\ 3274 topViewToken = %ld\ 3275 pluseEnabled = %s\ 3276 isFilePanel = %s\ 3277 MaskActivated = %s\ 3278 pulseRate = %lld\ 3279 waitingForMenu = %s\ 3280 minimized = %s\ 3281 Menu semaphore = %ld\ 3282 maxZoomHeight = %f\ 3283 maxZoomWidth = %f\ 3284 minWindHeight = %f\ 3285 minWindWidth = %f\ 3286 maxWindHeight = %f\ 3287 maxWindWidth = %f\ 3288 frame = ( %f, %f, %f, %f )\ 3289 look = %d\ 3290 feel = %d\ 3291 lastViewToken = %ld\ 3292 pulseRUNNER = %s\n", 3293 fTopViewToken, 3294 fPulseEnabled==true?"Yes":"No", 3295 fIsFilePanel==true?"Yes":"No", 3296 fMaskActivated==true?"Yes":"No", 3297 fPulseRate, 3298 fWaitingForMenu==true?"Yes":"No", 3299 fMinimized==true?"Yes":"No", 3300 fMenuSem, 3301 fMaxZoomHeight, 3302 fMaxZoomWidth, 3303 fMinWindHeight, 3304 fMinWindWidth, 3305 fMaxWindHeight, 3306 fMaxWindWidth, 3307 fFrame.left, fFrame.top, fFrame.right, fFrame.bottom, 3308 (int16)fLook, 3309 (int16)fFeel, 3310 fLastViewToken, 3311 fPulseRunner!=NULL?"In place":"NULL"); 3312 } 3313 3314 /* 3315 TODO list: 3316 3317 *) take care of temporarely events mask!!! 3318 *) what's with this flag B_ASYNCHRONOUS_CONTROLS ? 3319 *) test arguments for SetWindowAligment 3320 *) call hook functions: MenusBeginning, MenusEnded. Add menu activation code. 3321 3322 * add handlers for B_VIEW_MOVED/RESIZED in DispatchMessage() 3323 * modify _UPDATE_ handler in DispatchMessage() 3324 */ 3325 3326 /* 3327 @log 3328 *modified ReadRawFromPort() and ConvertToMessage() methods to use BSession class. 3329 *modified/added B_VIEW_(MOVED/RESIZED) handlers in ConvertToMessage()/DispatchMessage() 3330 */ 3331