NETRootInfo Class

Common API for root window properties/protocols. More...

Header: #include <NETWM>
CMake: find_package(KF6 REQUIRED COMPONENTS KWindowSystem)
target_link_libraries(mytarget PRIVATE KF6::KWindowSystem)

Public Functions

NETRootInfo(xcb_connection_t *connection, int properties, int properties2, int screen = -1, bool doActivate = true)
NETRootInfo(xcb_connection_t *connection, xcb_window_t supportWindow, const char *wmName, int properties, int windowTypes, int states, int properties2, int actions, int screen = -1, bool doActivate = true)
NETRootInfo(const NETRootInfo &rootinfo)
void activate()
xcb_window_t activeWindow() const
const xcb_window_t *clientList() const
int clientListCount() const
const xcb_window_t *clientListStacking() const
int clientListStackingCount() const
void closeWindowRequest(xcb_window_t window)
int currentDesktop(bool ignore_viewport = false) const
int desktopGeometry() const
QSize desktopLayoutColumnsRows() const
int desktopLayoutCorner() const
int desktopLayoutOrientation() const
const char *desktopName(int desktop) const
int desktopViewport(int desktop) const
int event(xcb_generic_event_t *event)
(since 5.0) void event(xcb_generic_event_t *event, int *properties, int *properties2 = nullptr)
bool isSupported(int action) const
void moveResizeRequest(xcb_window_t window, int x_root, int y_root, int direction, xcb_button_t button = XCB_BUTTON_INDEX_ANY, int source)
void moveResizeWindowRequest(xcb_window_t window, int flags, int x, int y, int width, int height)
int numberOfDesktops(bool ignore_viewport = false) const
(since 5.0) int passedActions() const
(since 5.0) int passedProperties2() const
int passedProperties() const
(since 5.0) int passedStates() const
(since 5.0) int passedWindowTypes() const
void restackRequest(xcb_window_t window, int source, xcb_window_t above, int detail, xcb_timestamp_t timestamp)
xcb_window_t rootWindow() const
void sendPing(xcb_window_t window, xcb_timestamp_t timestamp)
void setActiveWindow(xcb_window_t window)
void setActiveWindow(xcb_window_t window, int src, xcb_timestamp_t timestamp, xcb_window_t active_window)
void setClientList(const xcb_window_t *windows, unsigned int count)
void setClientListStacking(const xcb_window_t *windows, unsigned int count)
void setCurrentDesktop(int desktop, bool ignore_viewport = false)
void setDesktopGeometry(const int &geometry)
void setDesktopLayout(int orientation, int columns, int rows, int corner)
void setDesktopName(int desktop, const char *desktopName)
void setDesktopViewport(int desktop, const int &viewport)
void setNumberOfDesktops(int numberOfDesktops)
void setShowingDesktop(bool showing)
(since 4.4) void setSupported(int property, bool on = true)
void setVirtualRoots(const xcb_window_t *windows, unsigned int count)
void setWorkArea(int desktop, const int &workArea)
void showWindowMenuRequest(xcb_window_t window, int device_id, int x_root, int y_root)
bool showingDesktop() const
xcb_window_t supportWindow() const
(since 5.0) int supportedActions() const
(since 5.0) int supportedProperties2() const
int supportedProperties() const
(since 5.0) int supportedStates() const
(since 5.0) int supportedWindowTypes() const
const xcb_window_t *virtualRoots() const
int virtualRootsCount() const
const char *wmName() const
int workArea(int desktop) const
xcb_connection_t *xcbConnection() const
const NETRootInfo &operator=(const NETRootInfo &rootinfo)

Protected Functions

virtual void addClient(xcb_window_t window)
virtual void changeActiveWindow(xcb_window_t window, int src, xcb_timestamp_t timestamp, xcb_window_t active_window)
virtual void changeCurrentDesktop(int desktop)
virtual void changeDesktopGeometry(int desktop, const int &geom)
virtual void changeDesktopViewport(int desktop, const int &viewport)
virtual void changeNumberOfDesktops(int numberOfDesktops)
virtual void changeShowingDesktop(bool showing)
virtual void closeWindow(xcb_window_t window)
virtual void gotPing(xcb_window_t window, xcb_timestamp_t timestamp)
virtual void moveResize(xcb_window_t window, int x_root, int y_root, unsigned long direction, xcb_button_t button, int source)
virtual void moveResizeWindow(xcb_window_t window, int flags, int x, int y, int width, int height)
virtual void removeClient(xcb_window_t window)
virtual void restackWindow(xcb_window_t window, int source, xcb_window_t above, int detail, xcb_timestamp_t timestamp)
virtual void showWindowMenu(xcb_window_t window, int device_id, int x_root, int y_root)
virtual void virtual_hook(int id, void *data)

Detailed Description

The NETRootInfo class provides a common API for clients and window managers to set/read/change properties on the root window as defined by the NET Window Manager Specification..

*

See also NET and NETWinInfo.

Member Function Documentation

NETRootInfo::NETRootInfo(xcb_connection_t *connection, int properties, int properties2, int screen = -1, bool doActivate = true)

Clients should use this constructor to create a NETRootInfo object, which will be used to query information set on the root window. The application role is automatically set to Client when using this constructor.

connection XCB connection

properties The properties the client is interested in.

properties2 The properties2 the client is interested in.

properties_size The number of elements in the properties array.

screen For Clients that support multiple screen (ie. "multiheaded") displays, the screen number may be explicitly defined. If this argument is omitted, the default screen will be used.

doActivate true to call activate() to do an initial data read/update of the query information. *

NETRootInfo::NETRootInfo(xcb_connection_t *connection, xcb_window_t supportWindow, const char *wmName, int properties, int windowTypes, int states, int properties2, int actions, int screen = -1, bool doActivate = true)

Window Managers should use this constructor to create a NETRootInfo object, which will be used to set/update information stored on the rootWindow. The application role is automatically set to WindowManager when using this constructor.

connection XCB connection

supportWindow The Window id of the supportWindow. The supportWindow must be created by the window manager as a child of the rootWindow. The supportWindow must not be destroyed until the Window Manager exits.

wmName A string which should be the window manager's name (ie. "KWin" or "Blackbox").

properties The properties the window manager supports

windowTypes The window types the window manager supports

states The states the window manager supports

properties2 The properties2 the window manager supports

actions The actions the window manager supports

screen For Window Managers that support multiple screen (ie. "multiheaded") displays, the screen number may be explicitly defined. If this argument is omitted, the default screen will be used.

doActivate true to activate the window *

NETRootInfo::NETRootInfo(const NETRootInfo &rootinfo)

Creates a shared copy of the specified NETRootInfo object.

rootinfo the NETRootInfo object to copy *

void NETRootInfo::activate()

Window Managers must call this after creating the NETRootInfo object, and before using any other method in the class. This method sets initial data on the root window and does other post-construction duties.

Clients must also call this after creating the object to do an initial data read/update. *

xcb_window_t NETRootInfo::activeWindow() const

Returns the active (focused) window.

Returns the id of the active window *

See also setActiveWindow().

[virtual protected] void NETRootInfo::addClient(xcb_window_t window)

A Client should subclass NETRootInfo and reimplement this function when it wants to know when a window has been added.

window the id of the window to add *

[virtual protected] void NETRootInfo::changeActiveWindow(xcb_window_t window, int src, xcb_timestamp_t timestamp, xcb_window_t active_window)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to change the active (focused) window.

window the id of the window to activate

src the source from which the request came

timestamp the timestamp of the user action causing this request

active_window active window of the requesting application, if any *

[virtual protected] void NETRootInfo::changeCurrentDesktop(int desktop)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to change the current desktop.

desktop the number of the desktop *

[virtual protected] void NETRootInfo::changeDesktopGeometry(int desktop, const int &geom)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to change the specified desktop geometry.

desktop the number of the desktop

geom the new size *

[virtual protected] void NETRootInfo::changeDesktopViewport(int desktop, const int &viewport)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to change the specified desktop viewport.

desktop the number of the desktop

viewport the new position of the viewport *

[virtual protected] void NETRootInfo::changeNumberOfDesktops(int numberOfDesktops)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to change the number of desktops.

numberOfDesktops the new number of desktops *

[virtual protected] void NETRootInfo::changeShowingDesktop(bool showing)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a pager made a request to change showing the desktop. See _NET_SHOWING_DESKTOP for details.

showing whether to activate the showing desktop mode *

const xcb_window_t *NETRootInfo::clientList() const

Returns an array of Window id's, which contain all managed windows.

Returns the array of Window id's

*

See also setClientList() and clientListCount().

int NETRootInfo::clientListCount() const

Returns the number of managed windows in clientList array.

Returns the number of managed windows in the clientList array

*

See also clientList().

const xcb_window_t *NETRootInfo::clientListStacking() const

Returns an array of Window id's, which contain all managed windows in stacking order.

Returns the array of Window id's in stacking order

*

See also setClientListStacking() and clientListStackingCount().

int NETRootInfo::clientListStackingCount() const

Returns the number of managed windows in the clientListStacking array.

Returns the number of Window id's in the client list

*

See also clientListStacking().

[virtual protected] void NETRootInfo::closeWindow(xcb_window_t window)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to close a window.

window the id of the window to close *

void NETRootInfo::closeWindowRequest(xcb_window_t window)

Clients (such as pagers/taskbars) that wish to close a window should call this function. This will send a request to the Window Manager, which usually can usually decide how to react to such requests.

window the id of the window to close *

int NETRootInfo::currentDesktop(bool ignore_viewport = false) const

Returns the current desktop.

Note: KDE uses virtual desktops and does not directly support viewport in any way. They are however mapped to virtual desktops if needed.

ignore_viewport if false, viewport is mapped to virtual desktops

Returns the number of the current desktop *

See also setCurrentDesktop().

int NETRootInfo::desktopGeometry() const

Returns the desktop geometry size.

Note: KDE uses virtual desktops and does not directly support viewport in any way. You should use calls for virtual desktops, viewport is mapped to them if needed.

Returns the size of the desktop *

See also setDesktopGeometry().

QSize NETRootInfo::desktopLayoutColumnsRows() const

Returns the desktop layout number of columns and rows. Note that either may be 0 (see _NET_DESKTOP_LAYOUT). *

int NETRootInfo::desktopLayoutCorner() const

Returns the desktop layout starting corner. *

int NETRootInfo::desktopLayoutOrientation() const

Returns the desktop layout orientation. *

const char *NETRootInfo::desktopName(int desktop) const

Returns the name for the specified desktop.

desktop the number of the desktop

Returns the name of the desktop *

See also setDesktopName().

int NETRootInfo::desktopViewport(int desktop) const

Returns the viewport of the specified desktop.

Note: KDE uses virtual desktops and does not directly support viewport in any way. You should use calls for virtual desktops, viewport is mapped to them if needed.

desktop the number of the desktop

Returns the position of the desktop's viewport *

See also setDesktopViewport().

int NETRootInfo::event(xcb_generic_event_t *event)

This function takes the passed XEvent and returns an OR'ed list of NETRootInfo properties that have changed. The new information will be read immediately by the class. This overloaded version returns only a single mask, and therefore cannot check state of all properties like the other variant.

event the event

Returns the properties *

[since 5.0] void NETRootInfo::event(xcb_generic_event_t *event, int *properties, int *properties2 = nullptr)

This function takes the passed xcb_generic_event_t and returns the updated properties in the passed in arguments.

The new information will be read immediately by the class. It is possible to pass in a null pointer in the arguments. In that case the passed in argument will obviously not be updated, but the class will process the information nevertheless.

event the event

properties The NET::Properties that changed

properties2 The NET::Properties2 that changed

This function was introduced in 5.0.

[virtual protected] void NETRootInfo::gotPing(xcb_window_t window, xcb_timestamp_t timestamp)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to receive replies to the _NET_WM_PING protocol.

window the window from which the reply came

timestamp timestamp of the ping

bool NETRootInfo::isSupported(int action) const

This is an overloaded function.

*

[virtual protected] void NETRootInfo::moveResize(xcb_window_t window, int x_root, int y_root, unsigned long direction, xcb_button_t button, int source)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to start a move/resize.

window The window that wants to move/resize

x_root X position of the cursor relative to the root window.

y_root Y position of the cursor relative to the root window.

direction One of NET::Direction (see base class documentation for a description of the different directions).

button the button which should be pressed.

source who initiated the move resize operation. *

void NETRootInfo::moveResizeRequest(xcb_window_t window, int x_root, int y_root, int direction, xcb_button_t button = XCB_BUTTON_INDEX_ANY, int source)

Clients (such as pagers/taskbars) that wish to start a WMMoveResize (where the window manager controls the resize/movement, i.e. _NET_WM_MOVERESIZE) should call this function. This will send a request to the Window Manager.

window The client window that would be resized/moved.

x_root X position of the cursor relative to the root window.

y_root Y position of the cursor relative to the root window.

direction One of NET::Direction (see base class documentation for a description of the different directions).

button the button which should be pressed.

source who initiated the move resize operation. *

[virtual protected] void NETRootInfo::moveResizeWindow(xcb_window_t window, int flags, int x, int y, int width, int height)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a pager made a request to move/resize a window. See _NET_MOVERESIZE_WINDOW for details.

window the id of the window to more/resize

flags Flags specifying the operation (see _NET_MOVERESIZE_WINDOW description)

x Requested X position for the window

y Requested Y position for the window

width Requested width for the window

height Requested height for the window *

void NETRootInfo::moveResizeWindowRequest(xcb_window_t window, int flags, int x, int y, int width, int height)

Clients (such as pagers/taskbars) that wish to move/resize a window using WM2MoveResizeWindow (_NET_MOVERESIZE_WINDOW) should call this function. This will send a request to the Window Manager. See _NET_MOVERESIZE_WINDOW description for details.

window The client window that would be resized/moved.

flags Flags specifying the operation (see _NET_MOVERESIZE_WINDOW description)

x Requested X position for the window

y Requested Y position for the window

width Requested width for the window

height Requested height for the window *

int NETRootInfo::numberOfDesktops(bool ignore_viewport = false) const

Returns the number of desktops.

Note: KDE uses virtual desktops and does not directly support viewport in any way. They are however mapped to virtual desktops if needed.

ignore_viewport if false, viewport is mapped to virtual desktops

Returns the number of desktops *

See also setNumberOfDesktops().

[since 5.0] int NETRootInfo::passedActions() const

Returns the actions argument passed to the constructor.

This function was introduced in 5.0.

See also passedProperties(), passedProperties2(), passedStates(), and passedWindowTypes().

[since 5.0] int NETRootInfo::passedProperties2() const

Returns the properties2 argument passed to the constructor.

This function was introduced in 5.0.

See also passedProperties(), passedStates(), passedWindowTypes(), and passedActions().

int NETRootInfo::passedProperties() const

Returns the properties argument passed to the constructor.

See also passedProperties2(), passedStates(), passedWindowTypes(), and passedActions().

[since 5.0] int NETRootInfo::passedStates() const

Returns the states argument passed to the constructor.

This function was introduced in 5.0.

See also passedProperties(), passedProperties2(), passedWindowTypes(), and passedActions().

[since 5.0] int NETRootInfo::passedWindowTypes() const

Returns the windowTypes argument passed to the constructor.

This function was introduced in 5.0.

See also passedProperties(), passedProperties2(), passedStates(), and passedActions().

[virtual protected] void NETRootInfo::removeClient(xcb_window_t window)

A Client should subclass NETRootInfo and reimplement this function when it wants to know when a window has been removed.

window the id of the window to remove *

void NETRootInfo::restackRequest(xcb_window_t window, int source, xcb_window_t above, int detail, xcb_timestamp_t timestamp)

Sends the _NET_RESTACK_WINDOW request. *

[virtual protected] void NETRootInfo::restackWindow(xcb_window_t window, int source, xcb_window_t above, int detail, xcb_timestamp_t timestamp)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to restack a window. See _NET_RESTACK_WINDOW for details.

window the id of the window to restack

source the source of the request

above other window in the restack request

detail restack detail

timestamp the timestamp of the request *

xcb_window_t NETRootInfo::rootWindow() const

Returns the Window id of the rootWindow. *

void NETRootInfo::sendPing(xcb_window_t window, xcb_timestamp_t timestamp)

Sends a ping with the given timestamp to the window, using the _NET_WM_PING protocol.

void NETRootInfo::setActiveWindow(xcb_window_t window)

Sets the active (focused) window the specified window. This should be used only in the window manager mode.

window the if of the new active window *

See also activeWindow().

void NETRootInfo::setActiveWindow(xcb_window_t window, int src, xcb_timestamp_t timestamp, xcb_window_t active_window)

Requests that the specified window becomes the active (focused) one.

window the id of the new active window

src whether the request comes from normal application or from a pager or similar tool

timestamp X server timestamp of the user action that caused the request

active_window active window of the requesting application, if any *

void NETRootInfo::setClientList(const xcb_window_t *windows, unsigned int count)

Sets the list of managed windows on the Root/Desktop window.

windows The array of Window id's

count The number of windows in the array *

See also clientList().

void NETRootInfo::setClientListStacking(const xcb_window_t *windows, unsigned int count)

Sets the list of managed windows in stacking order on the Root/Desktop window.

windows The array of Window id's

count The number of windows in the array. *

See also clientListStacking().

void NETRootInfo::setCurrentDesktop(int desktop, bool ignore_viewport = false)

Sets the current desktop to the specified desktop.

Note: KDE uses virtual desktops and does not directly support viewport in any way. It is however mapped to virtual desktops if needed.

desktop the number of the desktop

ignore_viewport if false, viewport is mapped to virtual desktops *

See also currentDesktop().

void NETRootInfo::setDesktopGeometry(const int &geometry)

Sets the desktop geometry to the specified geometry.

Note: KDE uses virtual desktops and does not directly support viewport in any way. You should use calls for virtual desktops, viewport is mapped to them if needed.

geometry the new size of the desktop *

See also desktopGeometry().

void NETRootInfo::setDesktopLayout(int orientation, int columns, int rows, int corner)

Sets the desktop layout. This is set by the pager. When setting, the pager must own the _NET_DESKTOP_LAYOUT_Sn manager selection. See _NET_DESKTOP_LAYOUT for details. *

void NETRootInfo::setDesktopName(int desktop, const char *desktopName)

Sets the name of the specified desktop.

Note: KDE uses virtual desktops and does not directly support viewport in any way. Viewport is mapped to virtual desktops if needed, but not for this call.

desktop the number of the desktop

desktopName the new name of the desktop *

See also desktopName().

void NETRootInfo::setDesktopViewport(int desktop, const int &viewport)

Sets the viewport for the current desktop to the specified point.

Note: KDE uses virtual desktops and does not directly support viewport in any way. You should use calls for virtual desktops, viewport is mapped to them if needed.

desktop the number of the desktop

viewport the new position of the desktop's viewport *

See also desktopViewport().

void NETRootInfo::setNumberOfDesktops(int numberOfDesktops)

Sets the number of desktops to the specified number.

Note: KDE uses virtual desktops and does not directly support viewport in any way. Viewport is mapped to virtual desktops if needed, but not for this call.

numberOfDesktops the number of desktops *

See also numberOfDesktops().

void NETRootInfo::setShowingDesktop(bool showing)

Sets the _NET_SHOWING_DESKTOP status (whether desktop is being shown).

See also showingDesktop().

[since 4.4] void NETRootInfo::setSupported(int property, bool on = true)

This is an overloaded function.

*

This function was introduced in 4.4.

void NETRootInfo::setVirtualRoots(const xcb_window_t *windows, unsigned int count)

Sets the list of virtual root windows on the root window.

windows The array of Window id's

count The number of windows in the array. *

See also virtualRoots().

void NETRootInfo::setWorkArea(int desktop, const int &workArea)

Sets the workarea for the specified desktop

desktop the number of the desktop

workArea the new work area of the desktop *

See also workArea().

[virtual protected] void NETRootInfo::showWindowMenu(xcb_window_t window, int device_id, int x_root, int y_root)

A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when a Client made a request to show a window menu.

window The window that wants to move/resize

device_id GTK device id.

x_root X position of the cursor relative to the root window.

y_root Y position of the cursor relative to the root window. *

void NETRootInfo::showWindowMenuRequest(xcb_window_t window, int device_id, int x_root, int y_root)

Clients that wish to show the window menu using WM2GTKShowWindowMenu (_GTK_SHOW_WINDOW_MENU) should call this function. This will send a request to the Window Manager. See _GTK_SHOW_WINDOW_MENU description for details.

window The client window that would be resized/moved.

device_id GTK device id

x Requested X position for the menu relative to the root window

y Requested Y position for the menu relative to the root window *

bool NETRootInfo::showingDesktop() const

Returns the status of _NET_SHOWING_DESKTOP.

See also setShowingDesktop().

xcb_window_t NETRootInfo::supportWindow() const

Returns the Window id of the supportWindow. *

[since 5.0] int NETRootInfo::supportedActions() const

* In the Window Manager mode, this is equivalent to the actions * argument passed to the constructor. In the Client mode, if * NET::Supported was passed in the properties argument, the returned * value are all actions supported by the Window Manager. Other supported * protocols and properties are returned by the specific methods. *

*

*

* *

This function was introduced in 5.0.

See also supportedProperties(), supportedProperties2(), supportedStates(), and supportedWindowTypes().

[since 5.0] int NETRootInfo::supportedProperties2() const

In the Window Manager mode, this is equivalent to the properties2 argument passed to the constructor. In the Client mode, if NET::Supported was passed in the properties argument, the returned value are all properties2 supported by the Window Manager. Other supported protocols and properties are returned by the specific methods.

This function was introduced in 5.0.

See also supportedProperties(), supportedStates(), supportedWindowTypes(), and supportedActions().

int NETRootInfo::supportedProperties() const

In the Window Manager mode, this is equivalent to the properties argument passed to the constructor. In the Client mode, if NET::Supported was passed in the properties argument, the returned value are all properties supported by the Window Manager. Other supported protocols and properties are returned by the specific methods.

*

See also supportedProperties2(), supportedStates(), supportedWindowTypes(), and supportedActions().

[since 5.0] int NETRootInfo::supportedStates() const

* In the Window Manager mode, this is equivalent to the states * argument passed to the constructor. In the Client mode, if * NET::Supported was passed in the properties argument, the returned * value are all states supported by the Window Manager. Other supported * protocols and properties are returned by the specific methods. *

*

*

* *

This function was introduced in 5.0.

See also supportedProperties(), supportedProperties2(), supportedWindowTypes(), and supportedActions().

[since 5.0] int NETRootInfo::supportedWindowTypes() const

* In the Window Manager mode, this is equivalent to the windowTypes * argument passed to the constructor. In the Client mode, if * NET::Supported was passed in the properties argument, the returned * value are all window types supported by the Window Manager. Other supported * protocols and properties are returned by the specific methods. *

*

*

* *

This function was introduced in 5.0.

See also supportedProperties(), supportedProperties2(), supportedStates(), and supportedActions().

const xcb_window_t *NETRootInfo::virtualRoots() const

Returns an array of Window id's, which contain the virtual root windows.

Returns the array of Window id's

*

See also setVirtualRoots() and virtualRootsCount().

int NETRootInfo::virtualRootsCount() const

Returns the number of window in the virtualRoots array.

Returns the number of Window id's in the virtual root array

*

See also virtualRoots().

[virtual protected] void NETRootInfo::virtual_hook(int id, void *data)

Virtual hook, used to add new "virtual" functions while maintaining binary compatibility. Unused in this class.

const char *NETRootInfo::wmName() const

Returns the name of the Window Manager. *

int NETRootInfo::workArea(int desktop) const

Returns the workArea for the specified desktop.

desktop the number of the desktop

Returns the size of the work area *

See also setWorkArea().

xcb_connection_t *NETRootInfo::xcbConnection() const

Returns the xcb connection used. *

const NETRootInfo &NETRootInfo::operator=(const NETRootInfo &rootinfo)

Assignment operator. Ensures that the shared data reference counts are correct. *