1 /* 2 * Copyright 2010, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Clemens Zeidler <haiku@clemens-zeidler.de> 7 */ 8 9 10 #include "WindowStack.h" 11 12 #include <new> 13 14 #include <Window.h> 15 16 #include <ApplicationPrivate.h> 17 #include <MessengerPrivate.h> 18 #include <PortLink.h> 19 #include <ServerProtocol.h> 20 21 #include "StackAndTilePrivate.h" 22 23 24 using namespace BPrivate; 25 26 27 BWindowStack::BWindowStack(BWindow* window) 28 : 29 fLink(NULL) 30 { 31 port_id receivePort = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, 32 "w_stack<app_server"); 33 if (receivePort != B_OK) 34 fLink = new(std::nothrow) BPrivate::PortLink( 35 window->fLink->SenderPort(), receivePort); 36 } 37 38 39 BWindowStack::~BWindowStack() 40 { 41 if (fLink) 42 delete_port(fLink->ReceiverPort()); 43 delete fLink; 44 } 45 46 47 status_t 48 BWindowStack::InitCheck() 49 { 50 if (!fLink) 51 return B_NO_MEMORY; 52 return B_OK; 53 } 54 55 56 status_t 57 BWindowStack::AddWindow(BWindow* window) 58 { 59 BMessenger messenger(window); 60 return AddWindow(messenger); 61 } 62 63 64 status_t 65 BWindowStack::AddWindow(BMessenger& window) 66 { 67 return AddWindowAt(window, -1); 68 } 69 70 71 status_t 72 BWindowStack::AddWindowAt(BWindow* window, int32 position) 73 { 74 BMessenger messenger(window); 75 return AddWindowAt(messenger, position); 76 } 77 78 79 status_t 80 BWindowStack::AddWindowAt(BMessenger& window, int32 position) 81 { 82 _StartMessage(kAddWindowToStack); 83 84 _AttachMessenger(window); 85 fLink->Attach<int32>(position); 86 87 int32 code = B_ERROR; 88 if (fLink->FlushWithReply(code) != B_OK) 89 return code; 90 91 return B_OK; 92 } 93 94 95 status_t 96 BWindowStack::RemoveWindow(BWindow* window) 97 { 98 BMessenger messenger(window); 99 return RemoveWindow(messenger); 100 } 101 102 103 status_t 104 BWindowStack::RemoveWindow(BMessenger& window) 105 { 106 _StartMessage(kRemoveWindowFromStack); 107 _AttachMessenger(window); 108 109 if (fLink->Flush() != B_OK) 110 return B_ERROR; 111 112 return B_OK; 113 } 114 115 116 status_t 117 BWindowStack::RemoveWindowAt(int32 position, BMessenger* window) 118 { 119 _StartMessage(kRemoveWindowFromStackAt); 120 fLink->Attach<int32>(position); 121 122 int32 code = B_ERROR; 123 if (fLink->FlushWithReply(code) != B_OK) 124 return code; 125 126 if (window == NULL) 127 return B_OK; 128 129 return _ReadMessenger(*window); 130 } 131 132 133 int32 134 BWindowStack::CountWindows() 135 { 136 _StartMessage(kCountWindowsOnStack); 137 138 int32 code = B_ERROR; 139 fLink->FlushWithReply(code); 140 if (code != B_OK) 141 return -1; 142 143 int32 count; 144 if (fLink->Read<int32>(&count) != B_OK) 145 return -1; 146 147 return count; 148 } 149 150 151 status_t 152 BWindowStack::WindowAt(int32 position, BMessenger& messenger) 153 { 154 _StartMessage(kWindowOnStackAt); 155 fLink->Attach<int32>(position); 156 157 int32 code = B_ERROR; 158 fLink->FlushWithReply(code); 159 if (code != B_OK) 160 return code; 161 162 return _ReadMessenger(messenger); 163 } 164 165 166 bool 167 BWindowStack::HasWindow(BWindow* window) 168 { 169 BMessenger messenger(window); 170 return HasWindow(messenger); 171 } 172 173 174 bool 175 BWindowStack::HasWindow(BMessenger& window) 176 { 177 _StartMessage(kStackHasWindow); 178 _AttachMessenger(window); 179 180 int32 code = B_ERROR; 181 fLink->FlushWithReply(code); 182 if (code != B_OK) 183 return code; 184 185 bool hasWindow; 186 if (fLink->Read<bool>(&hasWindow) != B_OK) 187 return false; 188 189 return hasWindow; 190 } 191 192 193 status_t 194 BWindowStack::_AttachMessenger(BMessenger& window) 195 { 196 BMessenger::Private messengerPrivate(window); 197 fLink->Attach<port_id>(messengerPrivate.Port()); 198 fLink->Attach<int32>(messengerPrivate.Token()); 199 return fLink->Attach<team_id>(messengerPrivate.Team()); 200 } 201 202 203 status_t 204 BWindowStack::_ReadMessenger(BMessenger& window) 205 { 206 port_id port; 207 int32 token; 208 team_id team; 209 fLink->Read<port_id>(&port); 210 fLink->Read<int32>(&token); 211 status_t status = fLink->Read<team_id>(&team); 212 if (status != B_OK) 213 return status; 214 BMessenger::Private messengerPrivate(window); 215 messengerPrivate.SetTo(team, port, token); 216 return B_OK; 217 } 218 219 220 status_t 221 BWindowStack::_StartMessage(int32 what) 222 { 223 fLink->StartMessage(AS_TALK_TO_DESKTOP_LISTENER); 224 fLink->Attach<port_id>(fLink->ReceiverPort()); 225 fLink->Attach<int32>(kMagicSATIdentifier); 226 return fLink->Attach<int32>(what); 227 } 228