mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Add client protocols and swaybg skeleton
This commit is contained in:
		
							parent
							
								
									45a50d5afe
								
							
						
					
					
						commit
						eccf0b2598
					
				
					 5 changed files with 347 additions and 182 deletions
				
			
		| 
						 | 
					@ -85,9 +85,11 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sway_inc = include_directories('include')
 | 
					sway_inc = include_directories('include')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subdir('protocols')
 | 
				
			||||||
subdir('common')
 | 
					subdir('common')
 | 
				
			||||||
subdir('sway')
 | 
					subdir('sway')
 | 
				
			||||||
subdir('swaymsg')
 | 
					subdir('swaymsg')
 | 
				
			||||||
 | 
					subdir('swaybg')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config = configuration_data()
 | 
					config = configuration_data()
 | 
				
			||||||
config.set('sysconfdir', join_paths(prefix, sysconfdir))
 | 
					config.set('sysconfdir', join_paths(prefix, sysconfdir))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								protocols/meson.build
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								protocols/meson.build
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wayland_scanner = find_program('wayland-scanner')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wayland_scanner_server = generator(
 | 
				
			||||||
 | 
						wayland_scanner,
 | 
				
			||||||
 | 
						output: '@BASENAME@-protocol.h',
 | 
				
			||||||
 | 
						arguments: ['server-header', '@INPUT@', '@OUTPUT@'],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wayland_scanner_code = generator(
 | 
				
			||||||
 | 
						wayland_scanner,
 | 
				
			||||||
 | 
						output: '@BASENAME@-protocol.c',
 | 
				
			||||||
 | 
						arguments: ['code', '@INPUT@', '@OUTPUT@'],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wayland_scanner_client = generator(
 | 
				
			||||||
 | 
						wayland_scanner,
 | 
				
			||||||
 | 
						output: '@BASENAME@-client-protocol.h',
 | 
				
			||||||
 | 
						arguments: ['client-header', '@INPUT@', '@OUTPUT@'],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protocols = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					client_protocols = [
 | 
				
			||||||
 | 
						'wlr-layer-shell-unstable-v1.xml',
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wl_protos_src = []
 | 
				
			||||||
 | 
					wl_protos_headers = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach p : protocols
 | 
				
			||||||
 | 
						xml = join_paths(p)
 | 
				
			||||||
 | 
						wl_protos_src += wayland_scanner_code.process(xml)
 | 
				
			||||||
 | 
						wl_protos_headers += wayland_scanner_server.process(xml)
 | 
				
			||||||
 | 
					endforeach
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach p : client_protocols
 | 
				
			||||||
 | 
						xml = join_paths(p)
 | 
				
			||||||
 | 
						wl_protos_headers += wayland_scanner_client.process(xml)
 | 
				
			||||||
 | 
					endforeach
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers,
 | 
				
			||||||
 | 
						dependencies: [wayland_client]) # for the include directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sway_protos = declare_dependency(
 | 
				
			||||||
 | 
						link_with: lib_wl_protos,
 | 
				
			||||||
 | 
						sources: wl_protos_headers,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										281
									
								
								protocols/wlr-layer-shell-unstable-v1.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								protocols/wlr-layer-shell-unstable-v1.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,281 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<protocol name="wlr_layer_shell_unstable_v1">
 | 
				
			||||||
 | 
					  <copyright>
 | 
				
			||||||
 | 
					    Copyright © 2017 Drew DeVault
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Permission to use, copy, modify, distribute, and sell this
 | 
				
			||||||
 | 
					    software and its documentation for any purpose is hereby granted
 | 
				
			||||||
 | 
					    without fee, provided that the above copyright notice appear in
 | 
				
			||||||
 | 
					    all copies and that both that copyright notice and this permission
 | 
				
			||||||
 | 
					    notice appear in supporting documentation, and that the name of
 | 
				
			||||||
 | 
					    the copyright holders not be used in advertising or publicity
 | 
				
			||||||
 | 
					    pertaining to distribution of the software without specific,
 | 
				
			||||||
 | 
					    written prior permission.  The copyright holders make no
 | 
				
			||||||
 | 
					    representations about the suitability of this software for any
 | 
				
			||||||
 | 
					    purpose.  It is provided "as is" without express or implied
 | 
				
			||||||
 | 
					    warranty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 | 
				
			||||||
 | 
					    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
				
			||||||
 | 
					    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | 
				
			||||||
 | 
					    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 | 
				
			||||||
 | 
					    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
				
			||||||
 | 
					    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 | 
				
			||||||
 | 
					    THIS SOFTWARE.
 | 
				
			||||||
 | 
					  </copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="zwlr_layer_shell_v1" version="1">
 | 
				
			||||||
 | 
					    <description summary="create surfaces that are layers of the desktop">
 | 
				
			||||||
 | 
					      Clients can use this interface to assign the surface_layer role to
 | 
				
			||||||
 | 
					      wl_surfaces. Such surfaces are assigned to a "layer" of the output and
 | 
				
			||||||
 | 
					      rendered with a defined z-depth respective to each other. They may also be
 | 
				
			||||||
 | 
					      anchored to the edges and corners of a screen and specify input handling
 | 
				
			||||||
 | 
					      semantics. This interface should be suitable for the implementation of
 | 
				
			||||||
 | 
					      many desktop shell components, and a broad number of other applications
 | 
				
			||||||
 | 
					      that interact with the desktop.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="get_layer_surface">
 | 
				
			||||||
 | 
					      <description summary="create a layer_surface from a surface">
 | 
				
			||||||
 | 
					        Create a layer surface for an existing surface. This assigns the role of
 | 
				
			||||||
 | 
					        layer_surface, or raises a protocol error if another role is already
 | 
				
			||||||
 | 
					        assigned.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Creating a layer surface from a wl_surface which has a buffer attached
 | 
				
			||||||
 | 
					        or committed is a client error, and any attempts by a client to attach
 | 
				
			||||||
 | 
					        or manipulate a buffer prior to the first layer_surface.configure call
 | 
				
			||||||
 | 
					        must also be treated as errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Clients can specify a namespace that defines the purpose of the layer
 | 
				
			||||||
 | 
					        surface.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
 | 
				
			||||||
 | 
					      <arg name="surface" type="object" interface="wl_surface"/>
 | 
				
			||||||
 | 
					      <arg name="output" type="object" interface="wl_output"/>
 | 
				
			||||||
 | 
					      <arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
 | 
				
			||||||
 | 
					      <arg name="namespace" type="string" summary="namespace for the layer surface"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="error">
 | 
				
			||||||
 | 
					      <entry name="role" value="0" summary="wl_surface has another role"/>
 | 
				
			||||||
 | 
					      <entry name="invalid_layer" value="1" summary="layer value is invalid"/>
 | 
				
			||||||
 | 
					      <entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="layer">
 | 
				
			||||||
 | 
					      <description summary="available layers for surfaces">
 | 
				
			||||||
 | 
					        These values indicate which layers a surface can be rendered in. They
 | 
				
			||||||
 | 
					        are ordered by z depth, bottom-most first. Traditional shell surfaces
 | 
				
			||||||
 | 
					        will typically be rendered between the bottom and top layers.
 | 
				
			||||||
 | 
					        Fullscreen shell surfaces are typically rendered at the top layer.
 | 
				
			||||||
 | 
					        Multiple surfaces can share a single layer, and ordering within a
 | 
				
			||||||
 | 
					        single layer is undefined.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <entry name="background" value="0"/>
 | 
				
			||||||
 | 
					      <entry name="bottom" value="1"/>
 | 
				
			||||||
 | 
					      <entry name="top" value="2"/>
 | 
				
			||||||
 | 
					      <entry name="overlay" value="3"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="zwlr_layer_surface_v1" version="1">
 | 
				
			||||||
 | 
					    <description summary="layer metadata interface">
 | 
				
			||||||
 | 
					      An interface that may be implemented by a wl_surface, for surfaces that
 | 
				
			||||||
 | 
					      are designed to be rendered as a layer of a stacked desktop-like
 | 
				
			||||||
 | 
					      environment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Layer surface state (size, anchor, exclusive zone, margin, interactivity)
 | 
				
			||||||
 | 
					      is double-buffered, and will be applied at the time wl_surface.commit of
 | 
				
			||||||
 | 
					      the corresponding wl_surface is called.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_size">
 | 
				
			||||||
 | 
					      <description summary="sets the size of the surface">
 | 
				
			||||||
 | 
					        Sets the size of the surface in surface-local coordinates. The
 | 
				
			||||||
 | 
					        compositor will display the surface centered with respect to its
 | 
				
			||||||
 | 
					        anchors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If you pass 0 for either value, the compositor will assign it and
 | 
				
			||||||
 | 
					        inform you of the assignment in the configure event. You must set your
 | 
				
			||||||
 | 
					        anchor to opposite edges in the dimensions you omit; not doing so is a
 | 
				
			||||||
 | 
					        protocol error. Both values are 0 by default.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Size is double-buffered, see wl_surface.commit.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="width" type="uint"/>
 | 
				
			||||||
 | 
					      <arg name="height" type="uint"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_anchor">
 | 
				
			||||||
 | 
					      <description summary="configures the anchor point of the surface">
 | 
				
			||||||
 | 
					        Requests that the compositor anchor the surface to the specified edges
 | 
				
			||||||
 | 
					        and corners. If two orthoginal edges are specified (e.g. 'top' and
 | 
				
			||||||
 | 
					        'left'), then the anchor point will be the intersection of the edges
 | 
				
			||||||
 | 
					        (e.g. the top left corner of the output); otherwise the anchor point
 | 
				
			||||||
 | 
					        will be centered on that edge, or in the center if none is specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Anchor is double-buffered, see wl_surface.commit.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="anchor" type="uint" enum="anchor"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_exclusive_zone">
 | 
				
			||||||
 | 
					      <description summary="configures the exclusive geometry of this surface">
 | 
				
			||||||
 | 
					        Requests that the compositor avoids occluding an area of the surface
 | 
				
			||||||
 | 
					        with other surfaces. The compositor's use of this information is
 | 
				
			||||||
 | 
					        implementation-dependent - do not assume that this region will not
 | 
				
			||||||
 | 
					        actually be occluded.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        A positive value is only meaningful if the surface is anchored to an
 | 
				
			||||||
 | 
					        edge, rather than a corner. The zone is the number of surface-local
 | 
				
			||||||
 | 
					        coordinates from the edge that are considered exclusive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Surfaces that do not wish to have an exclusive zone may instead specify
 | 
				
			||||||
 | 
					        how they should interact with surfaces that do. If set to zero, the
 | 
				
			||||||
 | 
					        surface indicates that it would like to be moved to avoid occluding
 | 
				
			||||||
 | 
					        surfaces with a positive excluzive zone. If set to -1, the surface
 | 
				
			||||||
 | 
					        indicates that it would not like to be moved to accomodate for other
 | 
				
			||||||
 | 
					        surfaces, and the compositor should extend it all the way to the edges
 | 
				
			||||||
 | 
					        it is anchored to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        For example, a panel might set its exclusive zone to 10, so that
 | 
				
			||||||
 | 
					        maximized shell surfaces are not shown on top of it. A notification
 | 
				
			||||||
 | 
					        might set its exclusive zone to 0, so that it is moved to avoid
 | 
				
			||||||
 | 
					        occluding the panel, but shell surfaces are shown underneath it. A
 | 
				
			||||||
 | 
					        wallpaper or lock screen might set their exclusive zone to -1, so that
 | 
				
			||||||
 | 
					        they stretch below or over the panel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The default value is 0.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Exclusive zone is double-buffered, see wl_surface.commit.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="zone" type="int"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_margin">
 | 
				
			||||||
 | 
					      <description summary="sets a margin from the anchor point">
 | 
				
			||||||
 | 
					        Requests that the surface be placed some distance away from the anchor
 | 
				
			||||||
 | 
					        point on the output, in surface-local coordinates. Setting this value
 | 
				
			||||||
 | 
					        for edges you are not anchored to has no effect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The exclusive zone includes the margin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Margin is double-buffered, see wl_surface.commit.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="top" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="right" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="bottom" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="left" type="int"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_keyboard_interactivity">
 | 
				
			||||||
 | 
					      <description summary="requests keyboard events">
 | 
				
			||||||
 | 
					        Set to 1 to request that the seat send keyboard events to this layer
 | 
				
			||||||
 | 
					        surface. For layers below the shell surface layer, the seat will use
 | 
				
			||||||
 | 
					        normal focus semantics. For layers above the shell surface layers, the
 | 
				
			||||||
 | 
					        seat will always give exclusive keyboard focus to the top-most layer
 | 
				
			||||||
 | 
					        which has keyboard interactivity set to true.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Layer surfaces receive pointer, touch, and tablet events normally. If
 | 
				
			||||||
 | 
					        you do not want to receive them, set the input region on your surface
 | 
				
			||||||
 | 
					        to an empty region.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Events is double-buffered, see wl_surface.commit.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="keyboard_interactivity" type="uint"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="get_popup">
 | 
				
			||||||
 | 
					      <description summary="assign this layer_surface as an xdg_popup parent">
 | 
				
			||||||
 | 
					        This assigns an xdg_popup's parent to this layer_surface.  This popup
 | 
				
			||||||
 | 
					        should have been created via xdg_surface::get_popup with the parent set
 | 
				
			||||||
 | 
					        to NULL, and this request must be invoked before committing the popup's
 | 
				
			||||||
 | 
					        initial state.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        See the documentation of xdg_popup for more details about what an
 | 
				
			||||||
 | 
					        xdg_popup is and how it is used.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="popup" type="object" interface="xdg_popup"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="ack_configure">
 | 
				
			||||||
 | 
					      <description summary="ack a configure event">
 | 
				
			||||||
 | 
					        When a configure event is received, if a client commits the
 | 
				
			||||||
 | 
					        surface in response to the configure event, then the client
 | 
				
			||||||
 | 
					        must make an ack_configure request sometime before the commit
 | 
				
			||||||
 | 
					        request, passing along the serial of the configure event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If the client receives multiple configure events before it
 | 
				
			||||||
 | 
					        can respond to one, it only has to ack the last configure event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        A client is not required to commit immediately after sending
 | 
				
			||||||
 | 
					        an ack_configure request - it may even ack_configure several times
 | 
				
			||||||
 | 
					        before its next surface commit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        A client may send multiple ack_configure requests before committing, but
 | 
				
			||||||
 | 
					        only the last request sent before a commit indicates which configure
 | 
				
			||||||
 | 
					        event the client really is responding to.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="serial" type="uint" summary="the serial from the configure event"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="destroy the layer_surface">
 | 
				
			||||||
 | 
					        This request destroys the layer surface.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="configure">
 | 
				
			||||||
 | 
					      <description summary="suggest a surface change">
 | 
				
			||||||
 | 
					        The configure event asks the client to resize its surface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Clients should arrange their surface for the new states, and then send
 | 
				
			||||||
 | 
					        an ack_configure request with the serial sent in this configure event at
 | 
				
			||||||
 | 
					        some point before committing the new surface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The client is free to dismiss all but the last configure event it
 | 
				
			||||||
 | 
					        received.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The width and height arguments specify the size of the window in
 | 
				
			||||||
 | 
					        surface-local coordinates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The size is a hint, in the sense that the client is free to ignore it if
 | 
				
			||||||
 | 
					        it doesn't resize, pick a smaller size (to satisfy aspect ratio or
 | 
				
			||||||
 | 
					        resize in steps of NxM pixels). If the client picks a smaller size and
 | 
				
			||||||
 | 
					        is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
 | 
				
			||||||
 | 
					        surface will be centered on this axis.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If the width or height arguments are zero, it means the client should
 | 
				
			||||||
 | 
					        decide its own window dimension.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="serial" type="uint"/>
 | 
				
			||||||
 | 
					      <arg name="width" type="uint"/>
 | 
				
			||||||
 | 
					      <arg name="height" type="uint"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="closed">
 | 
				
			||||||
 | 
					      <description summary="surface should be closed">
 | 
				
			||||||
 | 
					        The closed event is sent by the compositor when the surface will no
 | 
				
			||||||
 | 
					        longer be shown. The output may have been destroyed or the user may
 | 
				
			||||||
 | 
					        have asked for it to be removed. Further changes to the surface will be
 | 
				
			||||||
 | 
					        ignored. The client should destroy the resource after receiving this
 | 
				
			||||||
 | 
					        event, and create a new surface if they so choose.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="error">
 | 
				
			||||||
 | 
					      <entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
 | 
				
			||||||
 | 
					      <entry name="invalid_size" value="1" summary="size is invalid"/>
 | 
				
			||||||
 | 
					      <entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="anchor" bitfield="true">
 | 
				
			||||||
 | 
					      <entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
 | 
				
			||||||
 | 
					      <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
 | 
				
			||||||
 | 
					      <entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
 | 
				
			||||||
 | 
					      <entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					</protocol>
 | 
				
			||||||
							
								
								
									
										189
									
								
								swaybg/main.c
									
										
									
									
									
								
							
							
						
						
									
										189
									
								
								swaybg/main.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,20 +1,11 @@
 | 
				
			||||||
#include "wayland-desktop-shell-client-protocol.h"
 | 
					#include <ctype.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <ctype.h>
 | 
					 | 
				
			||||||
#include <wayland-client.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include "client/window.h"
 | 
					#include <time.h>
 | 
				
			||||||
#include "client/registry.h"
 | 
					#include <wayland-client.h>
 | 
				
			||||||
#include "client/cairo.h"
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
#include "log.h"
 | 
					 | 
				
			||||||
#include "list.h"
 | 
					 | 
				
			||||||
#include "util.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
list_t *surfaces;
 | 
					 | 
				
			||||||
struct registry *registry;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum scaling_mode {
 | 
					enum scaling_mode {
 | 
				
			||||||
	SCALING_MODE_STRETCH,
 | 
						SCALING_MODE_STRETCH,
 | 
				
			||||||
| 
						 | 
					@ -24,21 +15,11 @@ enum scaling_mode {
 | 
				
			||||||
	SCALING_MODE_TILE,
 | 
						SCALING_MODE_TILE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sway_terminate(int exit_code) {
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	for (i = 0; i < surfaces->length; ++i) {
 | 
					 | 
				
			||||||
		struct window *window = surfaces->items[i];
 | 
					 | 
				
			||||||
		window_teardown(window);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list_free(surfaces);
 | 
					 | 
				
			||||||
	registry_teardown(registry);
 | 
					 | 
				
			||||||
	exit(exit_code);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool is_valid_color(const char *color) {
 | 
					bool is_valid_color(const char *color) {
 | 
				
			||||||
	int len = strlen(color);
 | 
						int len = strlen(color);
 | 
				
			||||||
	if (len != 7 || color[0] != '#') {
 | 
						if (len != 7 || color[0] != '#') {
 | 
				
			||||||
		sway_log(L_ERROR, "%s is not a valid color for swaybg. Color should be specified as #rrggbb (no alpha).", color);
 | 
							wlr_log(L_ERROR, "%s is not a valid color for swaybg. "
 | 
				
			||||||
 | 
									"Color should be specified as #rrggbb (no alpha).", color);
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,162 +34,6 @@ bool is_valid_color(const char *color) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, const char **argv) {
 | 
					int main(int argc, const char **argv) {
 | 
				
			||||||
	init_log(L_INFO);
 | 
						wlr_log_init(L_DEBUG, NULL);
 | 
				
			||||||
	surfaces = create_list();
 | 
					 | 
				
			||||||
	registry = registry_poll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (argc != 4) {
 | 
					 | 
				
			||||||
		sway_abort("Do not run this program manually. See man 5 sway and look for output options.");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!registry->desktop_shell) {
 | 
					 | 
				
			||||||
		sway_abort("swaybg requires the compositor to support the desktop-shell extension.");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int desired_output = atoi(argv[1]);
 | 
					 | 
				
			||||||
	sway_log(L_INFO, "Using output %d of %d", desired_output, registry->outputs->length);
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	struct output_state *output = registry->outputs->items[desired_output];
 | 
					 | 
				
			||||||
	struct window *window = window_setup(registry,
 | 
					 | 
				
			||||||
			output->width, output->height, output->scale, false);
 | 
					 | 
				
			||||||
	if (!window) {
 | 
					 | 
				
			||||||
		sway_abort("Failed to create surfaces.");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	desktop_shell_set_background(registry->desktop_shell, output->output, window->surface);
 | 
					 | 
				
			||||||
	window_make_shell(window);
 | 
					 | 
				
			||||||
	list_add(surfaces, window);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (strcmp(argv[3], "solid_color") == 0 && is_valid_color(argv[2])) {
 | 
					 | 
				
			||||||
		cairo_set_source_u32(window->cairo, parse_color(argv[2]));
 | 
					 | 
				
			||||||
		cairo_paint(window->cairo);
 | 
					 | 
				
			||||||
		window_render(window);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
#ifdef WITH_GDK_PIXBUF
 | 
					 | 
				
			||||||
		GError *err = NULL;
 | 
					 | 
				
			||||||
		GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(argv[2], &err);
 | 
					 | 
				
			||||||
		if (!pixbuf) {
 | 
					 | 
				
			||||||
			sway_abort("Failed to load background image.");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
 | 
					 | 
				
			||||||
		g_object_unref(pixbuf);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		cairo_surface_t *image = cairo_image_surface_create_from_png(argv[2]);
 | 
					 | 
				
			||||||
#endif //WITH_GDK_PIXBUF
 | 
					 | 
				
			||||||
		if (!image) {
 | 
					 | 
				
			||||||
			sway_abort("Failed to read background image.");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) {
 | 
					 | 
				
			||||||
			sway_abort("Failed to read background image: %s."
 | 
					 | 
				
			||||||
#ifndef WITH_GDK_PIXBUF
 | 
					 | 
				
			||||||
					"\nSway was compiled without gdk_pixbuf support, so only"
 | 
					 | 
				
			||||||
					"\nPNG images can be loaded. This is the likely cause."
 | 
					 | 
				
			||||||
#endif //WITH_GDK_PIXBUF
 | 
					 | 
				
			||||||
					, cairo_status_to_string(cairo_surface_status(image)));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		double width = cairo_image_surface_get_width(image);
 | 
					 | 
				
			||||||
		double height = cairo_image_surface_get_height(image);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const char *scaling_mode_str = argv[3];
 | 
					 | 
				
			||||||
		enum scaling_mode scaling_mode = SCALING_MODE_STRETCH;
 | 
					 | 
				
			||||||
		if (strcmp(scaling_mode_str, "stretch") == 0) {
 | 
					 | 
				
			||||||
			scaling_mode = SCALING_MODE_STRETCH;
 | 
					 | 
				
			||||||
		} else if (strcmp(scaling_mode_str, "fill") == 0) {
 | 
					 | 
				
			||||||
			scaling_mode = SCALING_MODE_FILL;
 | 
					 | 
				
			||||||
		} else if (strcmp(scaling_mode_str, "fit") == 0) {
 | 
					 | 
				
			||||||
			scaling_mode = SCALING_MODE_FIT;
 | 
					 | 
				
			||||||
		} else if (strcmp(scaling_mode_str, "center") == 0) {
 | 
					 | 
				
			||||||
			scaling_mode = SCALING_MODE_CENTER;
 | 
					 | 
				
			||||||
		} else if (strcmp(scaling_mode_str, "tile") == 0) {
 | 
					 | 
				
			||||||
			scaling_mode = SCALING_MODE_TILE;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			sway_abort("Unsupported scaling mode: %s", scaling_mode_str);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		int wwidth = window->width * window->scale;
 | 
					 | 
				
			||||||
		int wheight = window->height * window->scale;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < surfaces->length; ++i) {
 | 
					 | 
				
			||||||
			struct window *window = surfaces->items[i];
 | 
					 | 
				
			||||||
			if (window_prerender(window) && window->cairo) {
 | 
					 | 
				
			||||||
				switch (scaling_mode) {
 | 
					 | 
				
			||||||
				case SCALING_MODE_STRETCH:
 | 
					 | 
				
			||||||
					cairo_scale(window->cairo,
 | 
					 | 
				
			||||||
							(double) wwidth / width,
 | 
					 | 
				
			||||||
							(double) wheight / height);
 | 
					 | 
				
			||||||
					cairo_set_source_surface(window->cairo, image, 0, 0);
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case SCALING_MODE_FILL:
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					double window_ratio = (double) wwidth / wheight;
 | 
					 | 
				
			||||||
					double bg_ratio = width / height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (window_ratio > bg_ratio) {
 | 
					 | 
				
			||||||
						double scale = (double) wwidth / width;
 | 
					 | 
				
			||||||
						cairo_scale(window->cairo, scale, scale);
 | 
					 | 
				
			||||||
						cairo_set_source_surface(window->cairo, image,
 | 
					 | 
				
			||||||
								0,
 | 
					 | 
				
			||||||
								(double) wheight/2 / scale - height/2);
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						double scale = (double) wheight / height;
 | 
					 | 
				
			||||||
						cairo_scale(window->cairo, scale, scale);
 | 
					 | 
				
			||||||
						cairo_set_source_surface(window->cairo, image,
 | 
					 | 
				
			||||||
								(double) wwidth/2 / scale - width/2,
 | 
					 | 
				
			||||||
								0);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				case SCALING_MODE_FIT:
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					double window_ratio = (double) wwidth / wheight;
 | 
					 | 
				
			||||||
					double bg_ratio = width / height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (window_ratio > bg_ratio) {
 | 
					 | 
				
			||||||
						double scale = (double) wheight / height;
 | 
					 | 
				
			||||||
						cairo_scale(window->cairo, scale, scale);
 | 
					 | 
				
			||||||
						cairo_set_source_surface(window->cairo, image,
 | 
					 | 
				
			||||||
								(double) wwidth/2 / scale - width/2,
 | 
					 | 
				
			||||||
								0);
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						double scale = (double) wwidth / width;
 | 
					 | 
				
			||||||
						cairo_scale(window->cairo, scale, scale);
 | 
					 | 
				
			||||||
						cairo_set_source_surface(window->cairo, image,
 | 
					 | 
				
			||||||
								0,
 | 
					 | 
				
			||||||
								(double) wheight/2 / scale - height/2);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				case SCALING_MODE_CENTER:
 | 
					 | 
				
			||||||
					cairo_set_source_surface(window->cairo, image,
 | 
					 | 
				
			||||||
							(double) wwidth/2 - width/2,
 | 
					 | 
				
			||||||
							(double) wheight/2 - height/2);
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case SCALING_MODE_TILE:
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
 | 
					 | 
				
			||||||
					cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
 | 
					 | 
				
			||||||
					cairo_set_source(window->cairo, pattern);
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				cairo_paint(window->cairo);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				window_render(window);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		cairo_surface_destroy(image);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (wl_display_dispatch(registry->display) != -1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < surfaces->length; ++i) {
 | 
					 | 
				
			||||||
		struct window *window = surfaces->items[i];
 | 
					 | 
				
			||||||
		window_teardown(window);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list_free(surfaces);
 | 
					 | 
				
			||||||
	registry_teardown(registry);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								swaybg/meson.build
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								swaybg/meson.build
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					executable(
 | 
				
			||||||
 | 
					    'swaybg',
 | 
				
			||||||
 | 
					    'main.c',
 | 
				
			||||||
 | 
					    include_directories: [sway_inc],
 | 
				
			||||||
 | 
					    dependencies: [wayland_client, sway_protos, jsonc, wlroots],
 | 
				
			||||||
 | 
					    link_with: [lib_sway_common],
 | 
				
			||||||
 | 
					    install: true
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue