/* * Copyright 2001-2020, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Adrian Oanca, adioanca@cotty.iren.ro * Stephan Aßmus, superstippi@gmx.de * Axel Dörfler, axeld@pinc-software.de * Andrej Spielmann, andrej.spielmann@seh.ox.ac.uk * Brecht Machiels, brecht@mos6581.org * Clemens Zeidler, haiku@clemens-zeidler.de * Joseph Groover, looncraz@looncraz.net * Tri-Edge AI * Jacob Secunda, secundja@gmail.com */ #ifndef DESKTOP_H #define DESKTOP_H #include #include #include #include #include #include #include #include #include #include #include "CursorManager.h" #include "DelayedMessage.h" #include "DesktopListener.h" #include "DesktopSettings.h" #include "EventDispatcher.h" #include "MessageLooper.h" #include "MultiLocker.h" #include "Screen.h" #include "ScreenManager.h" #include "ServerCursor.h" #include "StackAndTile.h" #include "VirtualScreen.h" #include "WindowList.h" #include "Workspace.h" #include "WorkspacePrivate.h" class BMessage; class DecorAddOn; class DrawingEngine; class HWInterface; class ServerApp; class Window; class WorkspacesView; struct server_read_only_memory; namespace BPrivate { class LinkSender; }; class Desktop : public DesktopObservable, public MessageLooper, public ScreenOwner { public: Desktop(uid_t userID, const char* targetScreen); virtual ~Desktop(); void RegisterListener(DesktopListener* listener); status_t Init(); uid_t UserID() const { return fUserID; } const char* TargetScreen() { return fTargetScreen; } virtual port_id MessagePort() const { return fMessagePort; } area_id SharedReadOnlyArea() const { return fSharedReadOnlyArea; } ::EventDispatcher& EventDispatcher() { return fEventDispatcher; } void BroadcastToAllApps(int32 code); void BroadcastToAllWindows(int32 code); int32 GetAllWindowTargets(DelayedMessage& message); int32 GetAllAppTargets(DelayedMessage& message); filter_result KeyEvent(uint32 what, int32 key, int32 modifiers); // Locking bool LockSingleWindow() { return fWindowLock.ReadLock(); } void UnlockSingleWindow() { fWindowLock.ReadUnlock(); } bool LockAllWindows() { return fWindowLock.WriteLock(); } void UnlockAllWindows() { fWindowLock.WriteUnlock(); } const MultiLocker& WindowLocker() { return fWindowLock; } // Mouse and cursor methods void SetCursor(ServerCursor* cursor); ServerCursorReference Cursor() const; void SetManagementCursor(ServerCursor* newCursor); void SetLastMouseState(const BPoint& position, int32 buttons, Window* windowUnderMouse); // for use by the mouse filter only // both mouse position calls require // the Desktop object to be locked // already void GetLastMouseState(BPoint* position, int32* buttons) const; // for use by ServerWindow CursorManager& GetCursorManager() { return fCursorManager; } // Screen and drawing related methods status_t SetScreenMode(int32 workspace, int32 id, const display_mode& mode, bool makeDefault); status_t GetScreenMode(int32 workspace, int32 id, display_mode& mode); status_t GetScreenFrame(int32 workspace, int32 id, BRect& frame); void RevertScreenModes(uint32 workspaces); status_t SetBrightness(int32 id, float brightness); MultiLocker& ScreenLocker() { return fScreenLock; } status_t LockDirectScreen(team_id team); status_t UnlockDirectScreen(team_id team); const ::VirtualScreen& VirtualScreen() const { return fVirtualScreen; } DrawingEngine* GetDrawingEngine() const { return fVirtualScreen.DrawingEngine(); } ::HWInterface* HWInterface() const { return fVirtualScreen.HWInterface(); } void RebuildAndRedrawAfterWindowChange( Window* window, BRegion& dirty); // the window lock must be held when calling // this function // ScreenOwner implementation virtual void ScreenRemoved(Screen* screen) {} virtual void ScreenAdded(Screen* screen) {} virtual void ScreenChanged(Screen* screen); virtual bool ReleaseScreen(Screen* screen) { return false; } // Workspace methods void SetWorkspaceAsync(int32 index, bool moveFocusWindow = false); void SetWorkspace(int32 index, bool moveFocusWindow = false); int32 CurrentWorkspace() { return fCurrentWorkspace; } Workspace::Private& WorkspaceAt(int32 index) { return fWorkspaces[index]; } status_t SetWorkspacesLayout(int32 columns, int32 rows); BRect WorkspaceFrame(int32 index) const; void StoreWorkspaceConfiguration(int32 index); void AddWorkspacesView(WorkspacesView* view); void RemoveWorkspacesView(WorkspacesView* view); // Window methods void SelectWindow(Window* window); void ActivateWindow(Window* window); void SendWindowBehind(Window* window, Window* behindOf = NULL, bool sendStack = true); void ShowWindow(Window* window); void HideWindow(Window* window, bool fromMinimize = false); void MinimizeWindow(Window* window, bool minimize); void MoveWindowBy(Window* window, float x, float y, int32 workspace = -1); void ResizeWindowBy(Window* window, float x, float y); void SetWindowOutlinesDelta(Window* window, BPoint delta); bool SetWindowTabLocation(Window* window, float location, bool isShifting); bool SetWindowDecoratorSettings(Window* window, const BMessage& settings); void SetWindowWorkspaces(Window* window, uint32 workspaces); void AddWindow(Window* window); void RemoveWindow(Window* window); bool AddWindowToSubset(Window* subset, Window* window); void RemoveWindowFromSubset(Window* subset, Window* window); void FontsChanged(Window* window); void ColorUpdated(Window* window, color_which which, rgb_color color); void SetWindowLook(Window* window, window_look look); void SetWindowFeel(Window* window, window_feel feel); void SetWindowFlags(Window* window, uint32 flags); void SetWindowTitle(Window* window, const char* title); Window* FocusWindow() const { return fFocus; } Window* FrontWindow() const { return fFront; } Window* BackWindow() const { return fBack; } Window* WindowAt(BPoint where); Window* MouseEventWindow() const { return fMouseEventWindow; } void SetMouseEventWindow(Window* window); void SetViewUnderMouse(const Window* window, int32 viewToken); int32 ViewUnderMouse(const Window* window); EventTarget* KeyboardEventTarget(); void SetFocusWindow(Window* window = NULL); void SetFocusLocked(const Window* window); Window* FindWindowByClientToken(int32 token, team_id teamID); EventTarget* FindTarget(BMessenger& messenger); void MarkDirty(BRegion& dirtyRegion, BRegion& exposeRegion); void MarkDirty(BRegion& region) { return MarkDirty(region, region); } void Redraw(); void RedrawBackground(); bool ReloadDecor(DecorAddOn* oldDecor); BRegion& BackgroundRegion() { return fBackgroundRegion; } void MinimizeApplication(team_id team); void BringApplicationToFront(team_id team); void WindowAction(int32 windowToken, int32 action); void WriteWindowList(team_id team, BPrivate::LinkSender& sender); void WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender); void WriteApplicationOrder(int32 workspace, BPrivate::LinkSender& sender); void WriteWindowOrder(int32 workspace, BPrivate::LinkSender& sender); //! The window lock must be held when accessing a window list! WindowList& CurrentWindows(); WindowList& AllWindows(); Window* WindowForClientLooperPort(port_id port); StackAndTile* GetStackAndTile() { return &fStackAndTile; } private: WindowList& _Windows(int32 index); void _FlushPendingColors(); void _LaunchInputServer(); void _GetLooperName(char* name, size_t size); void _PrepareQuit(); void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link); void _UpdateFloating(int32 previousWorkspace = -1, int32 nextWorkspace = -1, Window* mouseEventWindow = NULL); void _UpdateBack(); void _UpdateFront(bool updateFloating = true); void _UpdateFronts(bool updateFloating = true); bool _WindowHasModal(Window* window) const; bool _WindowCanHaveFocus(Window* window) const; void _WindowChanged(Window* window); void _WindowRemoved(Window* window); void _ShowWindow(Window* window, bool affectsOtherWindows = true); void _HideWindow(Window* window); void _UpdateSubsetWorkspaces(Window* window, int32 previousIndex = -1, int32 newIndex = -1); void _ChangeWindowWorkspaces(Window* window, uint32 oldWorkspaces, uint32 newWorkspaces); void _BringWindowsToFront(WindowList& windows, int32 list, bool wereVisible); Window* _LastFocusSubsetWindow(Window* window); bool _CheckSendFakeMouseMoved( const Window* lastWindowUnderMouse); void _SendFakeMouseMoved(Window* window = NULL); Screen* _DetermineScreenFor(BRect frame); void _RebuildClippingForAllWindows( BRegion& stillAvailableOnScreen); void _TriggerWindowRedrawing( BRegion& dirtyRegion, BRegion& exposeRegion); void _SetBackground(BRegion& background); status_t _ActivateApp(team_id team); void _SuspendDirectFrameBufferAccess(); void _ResumeDirectFrameBufferAccess(); void _ScreenChanged(Screen* screen); void _SetCurrentWorkspaceConfiguration(); void _SetWorkspace(int32 index, bool moveFocusWindow = false); private: friend class DesktopSettings; friend class LockedDesktopSettings; uid_t fUserID; char* fTargetScreen; ::VirtualScreen fVirtualScreen; ObjectDeleter fSettings; port_id fMessagePort; ::EventDispatcher fEventDispatcher; area_id fSharedReadOnlyArea; server_read_only_memory* fServerReadOnlyMemory; BLocker fApplicationsLock; BObjectList fApplications; sem_id fShutdownSemaphore; int32 fShutdownCount; ::Workspace::Private fWorkspaces[kMaxWorkspaces]; MultiLocker fScreenLock; BLocker fDirectScreenLock; team_id fDirectScreenTeam; int32 fCurrentWorkspace; int32 fPreviousWorkspace; WindowList fAllWindows; WindowList fSubsetWindows; WindowList fFocusList; Window* fLastWorkspaceFocus[kMaxWorkspaces]; BObjectList fWorkspacesViews; BLocker fWorkspacesLock; CursorManager fCursorManager; ServerCursorReference fCursor; ServerCursorReference fManagementCursor; MultiLocker fWindowLock; BRegion fBackgroundRegion; BRegion fScreenRegion; Window* fMouseEventWindow; const Window* fWindowUnderMouse; const Window* fLockedFocusWindow; int32 fViewUnderMouse; BPoint fLastMousePosition; int32 fLastMouseButtons; Window* fFocus; Window* fFront; Window* fBack; StackAndTile fStackAndTile; BMessage fPendingColors; }; #endif // DESKTOP_H