Aurelien Larcher
2017-10-27 a4b15adb6db25f5a0cf62562455b0adc2ec49103
Revert "Remove unsupported and broken dispswitch and xorg-input-hotkey packages"

This reverts commit 30b62a63059f5262682a74f069a6d605cfd7cecb.
16 files added
5 files modified
2974 ■■■■■ changed files
components/meta-packages/history/history 2 ●●●●● patch | view | raw | blame | history
components/meta-packages/install-types/Makefile 2 ●●● patch | view | raw | blame | history
components/meta-packages/install-types/includes/desktop_common 1 ●●●● patch | view | raw | blame | history
components/meta-packages/x11-server-utilities/Makefile 1 ●●●● patch | view | raw | blame | history
components/meta-packages/x11-server-utilities/x11-server-utilities.p5m 1 ●●●● patch | view | raw | blame | history
components/x11/dispswitch/Makefile 58 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/dispswitch.license 47 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/dispswitch.p5m 29 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/manifests/sample-manifest.p5m 28 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/src/Makefile 40 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/src/dispswitch.c 2052 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/src/dispswitch.man 102 ●●●●● patch | view | raw | blame | history
components/x11/dispswitch/src/dispswitch.o patch | view | raw | blame | history
components/x11/dispswitch/src/gnome-dispswitch.desktop 10 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/Makefile 70 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/manifests/sample-manifest.p5m 26 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/src/Makefile 39 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/src/config.h 70 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/src/hotkey.c 351 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/xf86-input-hotkey.license 20 ●●●●● patch | view | raw | blame | history
components/x11/xf86-input-hotkey/xorg-input-hotkey.p5m 25 ●●●●● patch | view | raw | blame | history
components/meta-packages/history/history
@@ -1161,8 +1161,6 @@
web/server/apache-22/module/apache-xml2enc@1.0.3,5.11-2017.0.0.1
web/server/lighttpd@1.4.23,5.11-0.134 web/server/lighttpd-14@1.4.23-0.151.1.8
web/urlgrabber@3.1.0-2015.0.2.0
x11/dispswitch@7.5,5.11-2017.0.0.1
x11/server/xorg/driver/xorg-input-hotkey@0.5.11,5.11-2017.0.0.2
x11/server/xorg/driver/xorg-video-apm@1.2.3,5.11-2015.0.0.0
x11/server/xorg/driver/xorg-video-ark@0.7.3,5.11-2015.0.0.0
x11/server/xorg/driver/xorg-video-chips@1.2.3,5.11-2015.0.0.0
components/meta-packages/install-types/Makefile
@@ -16,7 +16,7 @@
COMPONENT_NAME=        install-types
COMPONENT_VERSION=    0.1
COMPONENT_REVISION=    19
COMPONENT_REVISION=    18
COMPONENT_SUMMARY=    A meta-packages that install common applications for ISOs
include $(WS_MAKE_RULES)/ips.mk
components/meta-packages/install-types/includes/desktop_common
@@ -119,6 +119,7 @@
depend type=require fmri=x11/network/rstart
depend type=require fmri=x11/server/xephyr
depend type=require fmri=x11/server/xorg
depend type=require fmri=x11/server/xorg/driver/xorg-input-hotkey
depend type=require fmri=x11/server/xorg/driver/xorg-input-keyboard
depend type=require fmri=x11/server/xorg/driver/xorg-input-mouse
depend type=require fmri=x11/server/xorg/driver/xorg-input-synaptics
components/meta-packages/x11-server-utilities/Makefile
@@ -16,7 +16,6 @@
COMPONENT_NAME=          x11-server-utilities
COMPONENT_VERSION=      7.5
COMPONENT_REVISION=       1
COMPONENT_FMRI=          x11/x11-server-utilities
COMPONENT_CLASSIFICATION= Meta Packages/Group Packages
COMPONENT_SUMMARY=      X11 server state utilities
components/meta-packages/x11-server-utilities/x11-server-utilities.p5m
@@ -19,6 +19,7 @@
set name=info.classification value="$(COMPONENT_CLASSIFICATION)"
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
depend type=require fmri=pkg:/x11/dispswitch
depend type=require fmri=pkg:/x11/rgb
depend type=require fmri=pkg:/x11/xcmsdb
depend type=require fmri=pkg:/x11/xgamma
components/x11/dispswitch/Makefile
New file
@@ -0,0 +1,58 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2015 Aurelien Larcher
#
include ../../../make-rules/shared-macros.mk
COMPONENT_NAME=           dispswitch
COMPONENT_VERSION=        7.5
COMPONENT_FMRI=           x11/dispswitch
COMPONENT_CLASSIFICATION= System/X11
COMPONENT_SUMMARY=  dispswitch - utility for changing display configuration upon hotkey press
COMPONENT_SRC=      src
COMPONENT_PROJECT_URL = https://hg.java.net/hg/solaris-x11~x-s12-clone
COMPONENT_LICENSE=      MIT License,Oracle
COMPONENT_LICENSE_FILE= dispswitch.license
include $(WS_TOP)/make-rules/prep.mk
include $(WS_TOP)/make-rules/justmake.mk
include $(WS_TOP)/make-rules/ips.mk
PATH=/usr/gnu/bin:/usr/bin
COMPONENT_COMMON_ENV= CC=$(CC)
COMPONENT_COMMON_ENV+= CFLAGS="$(CFLAGS)"
COMPONENT_COMMON_ENV+= LDFLAGS="$(LDFLAGS)"
DISPSWITCH_BINDIR.32 =    $(USRBINDIR)
DISPSWITCH_BINDIR.64 =    $(USRBINDIR64)
COMPONENT_BUILD_ENV+= $(COMPONENT_COMMON_ENV)
COMPONENT_BUILD_ENV+= PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)"
COMPONENT_BUILD_ARGS= VPATH=$(SOURCE_DIR) -f $(SOURCE_DIR)/Makefile
COMPONENT_INSTALL_ENV+= INSTALL=$(INSTALL)
COMPONENT_INSTALL_ENV+= DESTDIR=$(PROTO_DIR)
COMPONENT_INSTALL_ENV+= PREFIX=$(USRDIR)
COMPONENT_INSTALL_ENV+= BINDIR=$(DISPSWITCH_BINDIR.$(BITS))
build: $(BUILD_32) $(BUILD_64)
install: $(INSTALL_32) $(INSTALL_64)
test: $(NO_TESTS)
REQUIRED_PACKAGES += system/library
REQUIRED_PACKAGES += x11/library/libx11
REQUIRED_PACKAGES += x11/library/libxrandr
components/x11/dispswitch/dispswitch.license
New file
@@ -0,0 +1,47 @@
/*
 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
 * Copyright © 2002 Hewlett Packard Company, Inc.
 * Copyright © 2006 Intel Corporation
 *
 * 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 (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
components/x11/dispswitch/dispswitch.p5m
New file
@@ -0,0 +1,29 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2016 Aurelien Larcher
#
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification value="$(COMPONENT_CLASSIFICATION)"
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
link path=usr/X11/bin/dispswitch target=../../bin/dispswitch
file path=etc/xdg/autostart/gnome-dispswitch.desktop
file path=usr/bin/$(MACH64)/dispswitch
file path=usr/bin/dispswitch
file path=usr/share/man/man1/dispswitch.1
components/x11/dispswitch/manifests/sample-manifest.p5m
New file
@@ -0,0 +1,28 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2016 <contributor>
#
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification value="$(COMPONENT_CLASSIFICATION)"
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
file path=etc/xdg/autostart/gnome-dispswitch.desktop
file path=usr/bin/$(MACH64)/dispswitch
file path=usr/bin/dispswitch
file path=usr/share/man/man1/dispswitch.1
components/x11/dispswitch/src/Makefile
New file
@@ -0,0 +1,40 @@
# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
PKGS= 'xrandr >= 1.2.0' x11
PKG_CFLAGS=`pkg-config --cflags $(PKGS)`
PKG_LIBS=`pkg-config --libs $(PKGS)`
CFLAGS+= $(PKG_CFLAGS)
LIBS= $(PKG_LIBS)
BINDIR:=${BINDIR}
dispswitch: dispswitch.c
    $(CC) -o $@ $(CFLAGS) $(LDFLAGS) dispswitch.c $(LIBS)
install: dispswitch dispswitch.man gnome-dispswitch.desktop
    mkdir -p $(DESTDIR)$(BINDIR) \
         $(DESTDIR)$(PREFIX)/share/man/man1 \
         $(DESTDIR)/etc/xdg/autostart
    $(INSTALL) -m 0555 dispswitch $(DESTDIR)$(BINDIR)
    $(INSTALL) -m 0444 dispswitch.man \
        $(DESTDIR)$(PREFIX)/share/man/man1/dispswitch.1
    $(INSTALL) -m 0444 gnome-dispswitch.desktop $(DESTDIR)/etc/xdg/autostart
components/x11/dispswitch/src/dispswitch.c
New file
@@ -0,0 +1,2052 @@
/*
 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
 * Copyright © 2002 Hewlett Packard Company, Inc.
 * Copyright © 2006 Intel Corporation
 *
 * 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 (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include <X11/Xproto.h>
#include <X11/extensions/Xrandr.h>
#include <X11/Xos.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/proc.h>
#include <unistd.h>
static char    *program_name;
static Display    *dpy = NULL;
static Window    root, win;
static int    screen;
static Bool    nosideview = False;
static Bool    verbose = False;
static Bool    testrun = False;
static int    had_error = 0;
static XErrorHandler    prev_handler;
static int    cur_keycode;
static struct timeval    time_val;
static Rotation    init_rotation;
static int     init_x;
static int     init_y;
static Bool    use_init_pos = False;
static Bool    need_off_deferred = False;
static void
usage(void)
{
    fprintf(stderr, "usage: %s [options]\n", program_name);
    fprintf(stderr, "  where options are:\n");
    fprintf(stderr, "  -toggle or -t\n");
    fprintf(stderr, "  -listen or -l\n");
    fprintf(stderr, "  -display <display> or -d <display>\n");
    fprintf(stderr, "  -key <key> or -k <key>\n");
    fprintf(stderr, "  -mod <modifier> or -m <modifier>\n");
    fprintf(stderr, "  -help\n");
    fprintf(stderr, "  -nosideview\n");
    fprintf(stderr, "  -verbose or -v\n");
    fprintf(stderr, "  -testrun\n");
    exit(1);
    /*NOTREACHED*/
}
static void
fatal (const char *format, ...)
{
    va_list ap;
    va_start (ap, format);
    fprintf (stderr, "%s exiting: ", program_name);
    vfprintf (stderr, format, ap);
    va_end (ap);
    exit (1);
    /*NOTREACHED*/
}
static int
cur_handler (
    Display *const err_display,
    XErrorEvent *const err_event)
{
    had_error = err_event -> error_code;
    return (0);
}
typedef enum _relation {
    left_of, right_of, above, below, same_as,
} relation_t;
typedef enum _changes {
    changes_none = 0,
    changes_crtc = (1 << 0),
    changes_mode = (1 << 1),
    changes_relation = (1 << 2),
    changes_position = (1 << 3),
} changes_t;
typedef enum _name_kind {
    name_none = 0,
    name_string = (1 << 0),
    name_xid = (1 << 1),
    name_index = (1 << 2),
} name_kind_t;
typedef struct {
    name_kind_t        kind;
    char            *string;
    XID                xid;
    int            index;
} name_t;
typedef struct _crtc crtc_t;
typedef struct _output    output_t;
struct _crtc {
    name_t        crtc;
    XRRCrtcInfo        *crtc_info;
    XRRModeInfo        *mode_info;
    int            x;
    int            y;
    Rotation        rotation;
    output_t        **outputs;
    int            noutput;
};
struct _output {
    struct _output  *next;
    changes_t        changes;
    name_t        output;
    XRROutputInfo   *output_info;
    name_t        crtc;
    crtc_t        *crtc_info;
    crtc_t        *current_crtc_info;
    name_t        mode;
    float        refresh;
    XRRModeInfo        *mode_info;
    name_t        addmode;
    relation_t        relation;
    struct _output  *relative_to;
    int            x, y;
    Rotation        rotation;
};
static output_t    *outputs = NULL;
static output_t    **outputs_tail = &outputs;
static crtc_t    *crtcs = NULL;
static int    num_crtcs;
static XRRScreenResources  *res = NULL;
static int    fb_width = 0, fb_height = 0;
static int    fb_width_mm = 0, fb_height_mm = 0;
static float    dpi = 0.0;
static Bool    dryrun = False;
static int    minWidth, maxWidth, minHeight, maxHeight;
#define     MAX_OUTPUT    3
#define     MAX_MODIFIERS    10
typedef struct _con_output  con_output_t;
struct _con_output {
    output_t        *output;
    XRRModeInfo        **smodes;
    int            nsmodes;
    Bool        on;
};
typedef struct _mod_key_table  mod_key_table_t;
struct _mod_key_table {
    char        *modname;
    unsigned int    mod;
};
static    con_output_t    con_outputs[MAX_OUTPUT];
static    con_output_t    dis_con_outputs[MAX_OUTPUT];
static    XRRModeInfo    *start_mode[MAX_OUTPUT];
static  XRRModeInfo    *new_mode[MAX_OUTPUT];
static    int     start = 0;
static    int    ncon;
static    int    dis_ncon;
static  Bool    do_not_switch = False;
static  Bool    did_init = False;
static mod_key_table_t    mod_key_table [MAX_MODIFIERS] = {
    {"none",    0},
    {"shift",     ShiftMask},
    {"lock",     LockMask},
    {"control",    ControlMask},
    {"mod1",     Mod1Mask},
    {"mod2",     Mod2Mask},
    {"mod3",     Mod3Mask},
    {"mod4",     Mod4Mask},
    {"mod5",     Mod5Mask},
    {"any",     AnyModifier}
};
static int
mode_height (XRRModeInfo *mode_info, Rotation rotation)
{
    switch (rotation & 0xf) {
    case RR_Rotate_0:
    case RR_Rotate_180:
    return mode_info->height;
    case RR_Rotate_90:
    case RR_Rotate_270:
    return mode_info->width;
    default:
    return 0;
    }
}
static int
mode_width (XRRModeInfo *mode_info, Rotation rotation)
{
    switch (rotation & 0xf) {
    case RR_Rotate_0:
    case RR_Rotate_180:
    return mode_info->width;
    case RR_Rotate_90:
    case RR_Rotate_270:
    return mode_info->height;
    default:
    return 0;
    }
}
/* v refresh frequency in Hz */
static float
mode_refresh (XRRModeInfo *mode_info)
{
    float rate;
    if (mode_info->hTotal && mode_info->vTotal)
    rate = ((float) mode_info->dotClock /
        ((float) mode_info->hTotal * (float) mode_info->vTotal));
    else
        rate = 0;
    return rate;
}
static void
init_name (name_t *name)
{
    name->kind = name_none;
}
static void
set_name_string (name_t *name, char *string)
{
    name->kind |= name_string;
    name->string = string;
}
static void
set_name_xid (name_t *name, XID xid)
{
    name->kind |= name_xid;
    name->xid = xid;
}
static void
set_name_index (name_t *name, int index)
{
    name->kind |= name_index;
    name->index = index;
}
static void
set_name_all (name_t *name, name_t *old)
{
    if (old->kind & name_xid)
    name->xid = old->xid;
    if (old->kind & name_string)
    name->string = old->string;
    if (old->kind & name_index)
    name->index = old->index;
    name->kind |= old->kind;
}
static output_t *
add_output (void)
{
    output_t *output = calloc (1, sizeof (output_t));
    if (!output)
    fatal ("out of memory");
    output->next = NULL;
    *outputs_tail = output;
    outputs_tail = &output->next;
    return output;
}
static output_t *
find_output (name_t *name)
{
    output_t *output;
    for (output = outputs; output; output = output->next)
    {
    name_kind_t common = name->kind & output->output.kind;
    if ((common & name_xid) && name->xid == output->output.xid)
        break;
    if ((common & name_string) && !strcmp (name->string, output->output.string))
        break;
    if ((common & name_index) && name->index == output->output.index)
        break;
    }
    return output;
}
static output_t *
find_output_by_xid (RROutput output)
{
    name_t  output_name;
    init_name (&output_name);
    set_name_xid (&output_name, output);
    return find_output (&output_name);
}
static crtc_t *
find_crtc (name_t *name)
{
    int        c;
    crtc_t  *crtc = NULL;
    for (c = 0; c < num_crtcs; c++)
    {
    name_kind_t common;
    crtc = &crtcs[c];
    common = name->kind & crtc->crtc.kind;
    if ((common & name_xid) && name->xid == crtc->crtc.xid)
        break;
    if ((common & name_string) && !strcmp (name->string, crtc->crtc.string))
        break;
    if ((common & name_index) && name->index == crtc->crtc.index)
        break;
    crtc = NULL;
    }
    return crtc;
}
static crtc_t *
find_crtc_by_xid (RRCrtc crtc)
{
    name_t  crtc_name;
    init_name (&crtc_name);
    set_name_xid (&crtc_name, crtc);
    return find_crtc (&crtc_name);
}
static XRRModeInfo *
find_mode (name_t *name)
{
    int        m;
    XRRModeInfo    *best = NULL;
    for (m = 0; m < res->nmode; m++)
    {
    XRRModeInfo *mode = &res->modes[m];
    if ((name->kind & name_xid) && name->xid == mode->id)
    {
        best = mode;
        break;
    }
    }
    return best;
}
static XRRModeInfo *
find_mode_by_xid (RRMode mode)
{
    name_t  mode_name;
    init_name (&mode_name);
    set_name_xid (&mode_name, mode);
    return find_mode (&mode_name);
}
static void
set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
{
    crtc_t  *crtc;
    /* sanity check output info */
    if (output_info->connection != RR_Disconnected && !output_info->nmode)
    fatal ("Output %s is not disconnected but has no modes\n",
           output_info->name);
    /* set output name and info */
    if (!(output->output.kind & name_xid))
    set_name_xid (&output->output, xid);
    if (!(output->output.kind & name_string))
    set_name_string (&output->output, output_info->name);
    output->output_info = output_info;
    crtc = find_crtc_by_xid (output->output_info->crtc);
    /* set position */
    if (crtc && crtc->crtc_info) {
    output->x = crtc->crtc_info->x;
    output->y = crtc->crtc_info->y;
    }
    /* set rotation */
    output->rotation &= ~0xf;
    if (crtc && crtc->crtc_info)
    output->rotation |= (crtc->crtc_info->rotation & 0xf);
    else
    output->rotation = RR_Rotate_0;
}
static void
get_crtcs (void)
{
    int        c;
    num_crtcs = res->ncrtc;
    if (crtcs)
    {
    for (c = 0; c < res->ncrtc; c++)
    {
        if (crtcs[c].crtc_info)
        XRRFreeCrtcInfo (crtcs[c].crtc_info);
    }
    free (crtcs);
    crtcs = NULL;
    }
    crtcs = calloc (num_crtcs, sizeof (crtc_t));
    if (!crtcs) fatal ("out of memory");
    for (c = 0; c < res->ncrtc; c++)
    {
    XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]);
    set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
    set_name_index (&crtcs[c].crtc, c);
    if (!crtc_info) fatal ("could not get crtc 0x%x information", res->crtcs[c]);
    crtcs[c].crtc_info = crtc_info;
    if (crtc_info->mode == None)
    {
        crtcs[c].mode_info = NULL;
        crtcs[c].x = 0;
        crtcs[c].y = 0;
        crtcs[c].rotation = RR_Rotate_0;
    }
    }
}
static void
crtc_add_output (crtc_t *crtc, output_t *output)
{
    if (crtc->outputs)
    crtc->outputs = realloc (crtc->outputs, (crtc->noutput + 1) * sizeof (output_t *));
    else
    {
    crtc->outputs = calloc (1, sizeof (output_t *));
    crtc->x = output->x;
    crtc->y = output->y;
    crtc->rotation = output->rotation;
    crtc->mode_info = output->mode_info;
    }
    if (!crtc->outputs) fatal ("out of memory");
    crtc->outputs[crtc->noutput++] = output;
}
static void
set_crtcs (void)
{
    output_t    *output;
    int        i;
    for (i = 0; i < ncon; i++) {
    output = con_outputs[i].output;
    if (!output->mode_info) continue;
        if (output->crtc_info)
        crtc_add_output (output->crtc_info, output);
    }
}
static void
reset_crtcs_for_outputs (void)
{
    output_t    *output;
    for (output = outputs; output; output = output->next)
    {
        if ((output->crtc_info) && (output->crtc_info->outputs)) {
            free (output->crtc_info->outputs);
            output->crtc_info = NULL;
        }
    }
}
static Status
crtc_disable (crtc_t *crtc)
{
    if (verbose)
        fprintf (stderr, "crtc %d (0x%lx) : disable\n", crtc->crtc.index, crtc->crtc.xid);
    if (dryrun)
    return RRSetConfigSuccess;
    return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
                 0, 0, None, RR_Rotate_0, NULL, 0);
}
static Status
crtc_revert (crtc_t *crtc)
{
    XRRCrtcInfo    *crtc_info = crtc->crtc_info;
    if (verbose)
        fprintf (stderr, "crtc %d: revert\n", crtc->crtc.index);
    if (dryrun)
    return RRSetConfigSuccess;
    return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
                crtc_info->x, crtc_info->y,
                crtc_info->mode, crtc_info->rotation,
                crtc_info->outputs, crtc_info->noutput);
}
static Status
crtc_apply (crtc_t *crtc)
{
    RROutput    *rr_outputs;
    int        o;
    Status    s;
    RRMode    mode = None;
    if (!crtc->mode_info)
    return RRSetConfigSuccess;
    rr_outputs = calloc (crtc->noutput, sizeof (RROutput));
    if (!rr_outputs)
    return BadAlloc;
    for (o = 0; o < crtc->noutput; o++)
    rr_outputs[o] = crtc->outputs[o]->output.xid;
    mode = crtc->mode_info->id;
    if (verbose) {
    fprintf (stderr, "crtc %d (0x%lx) : %12s %6.1f +%d+%d", crtc->crtc.index,
        crtc->crtc.xid,
        crtc->mode_info->name, mode_refresh (crtc->mode_info),
        crtc->x, crtc->y);
    for (o = 0; o < crtc->noutput; o++)
        fprintf (stderr, " \"%s\"", crtc->outputs[o]->output.string);
        fprintf (stderr, "\n");
    }
    if (dryrun)
    s = RRSetConfigSuccess;
    else
    s = XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
                  crtc->x, crtc->y, mode, crtc->rotation,
                  rr_outputs, crtc->noutput);
    free (rr_outputs);
    return s;
}
static void
screen_revert (void)
{
    if (verbose)
    fprintf (stderr, "screen %d: revert\n", screen);
    if (dryrun)
    return;
    XRRSetScreenSize (dpy, root,
              DisplayWidth (dpy, screen),
              DisplayHeight (dpy, screen),
              DisplayWidthMM (dpy, screen),
              DisplayHeightMM (dpy, screen));
}
static void
screen_apply (void)
{
    /* comment it out because DisplayWidth() does not reflect the
       change of fb_width and fb_height previously set by
       XRRSetScreenSize()
    */
    /*
    if (fb_width == DisplayWidth (dpy, screen) &&
    fb_height == DisplayHeight (dpy, screen) &&
    fb_width_mm == DisplayWidthMM (dpy, screen) &&
    fb_height_mm == DisplayHeightMM (dpy, screen))
    {
    return;
    }
    */
    if (verbose)
    fprintf (stderr, "screen %d: %dx%d %dx%d mm %6.2fdpi\n", screen,
        fb_width, fb_height, fb_width_mm, fb_height_mm, dpi);
    if (dryrun)
    return;
    XRRSetScreenSize (dpy, root, fb_width, fb_height,
              fb_width_mm, fb_height_mm);
}
static void
revert (void)
{
    int    c;
    /* first disable all crtcs */
    for (c = 0; c < res->ncrtc; c++)
    crtc_disable (&crtcs[c]);
    /* next reset screen size */
    screen_revert ();
    /* now restore all crtcs */
    for (c = 0; c < res->ncrtc; c++)
    crtc_revert (&crtcs[c]);
}
/*
 * uh-oh, something bad happened in the middle of changing
 * the configuration. Revert to the previous configuration
 * and bail
 */
static void
panic (Status s, crtc_t *crtc)
{
    int        c = crtc->crtc.index;
    char    *message;
    switch (s) {
    case RRSetConfigSuccess:        message = "succeeded";            break;
    case BadAlloc:            message = "out of memory";        break;
    case RRSetConfigFailed:        message = "failed";            break;
    case RRSetConfigInvalidConfigTime:    message = "invalid config time";    break;
    case RRSetConfigInvalidTime:    message = "invalid time";        break;
    default:                message = "unknown failure";        break;
    }
    fprintf (stderr, "%s: Configure crtc %d %s\n", program_name, c, message);
    revert ();
    exit (1);
}
static void
apply (void)
{
    Status  s;
    int        c;
    /*
     * Turn off any crtcs which are to be disabled or which are
     * larger than the target size
     */
    for (c = 0; c < res->ncrtc; c++)
    {
    crtc_t        *crtc = &crtcs[c];
    XRRCrtcInfo *crtc_info = crtc->crtc_info;
    /*
     * if this crtc is already disabled, skip it
     * Note server sets crtc_info->mode (before change)
     */
    if (crtc_info->mode == None)
        continue;
    /*
     * If this crtc is to be left enabled, make
     * sure the old size fits then new screen
     * When crtc->mode_info is null, the crtc is to be
     * disabled. Note set_crtcs () sets crtc->mode_info for
     * new mode (to be changed to).
     */
    if (crtc->mode_info)
    {
        XRRModeInfo    *old_mode = find_mode_by_xid (crtc_info->mode);
        int x, y, w, h;
        if (!old_mode)
        panic (RRSetConfigFailed, crtc);
        /* old position and size information */
        x = crtc_info->x;
        y = crtc_info->y;
        w = mode_width (old_mode, crtc_info->rotation);
        h = mode_height (old_mode, crtc_info->rotation);
        /* if it fits, skip it */
        if (x + w <= fb_width && y + h <= fb_height)
        continue;
    }
    if (need_off_deferred)
        /* Defer taking off */
        continue;
    s = crtc_disable (crtc);
    if (s != RRSetConfigSuccess)
        panic (s, crtc);
    }
    /*
     * Hold the server grabbed while messing with
     * the screen so that apps which notice the resize
     * event and ask for xinerama information from the server
     * receive up-to-date information
     */
    XGrabServer (dpy);
    /*
     * Set the screen size
     */
    screen_apply ();
    /*
     * Set crtcs
     */
    for (c = 0; c < res->ncrtc; c++)
    {
    crtc_t    *crtc = &crtcs[c];
    s = crtc_apply (crtc);
    if (s != RRSetConfigSuccess)
        panic (s, crtc);
    }
    /*
     * Release the server grab and let all clients
     * respond to the updated state
     */
    XUngrabServer (dpy);
}
/*
 * Use current output state to complete the output list
 */
static void
get_outputs (void)
{
    int        o;
    for (o = 0; o < res->noutput; o++)
    {
    XRROutputInfo    *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]);
    output_t    *output;
    name_t        output_name;
    if (!output_info) fatal ("could not get output 0x%x information", res->outputs[o]);
    set_name_xid (&output_name, res->outputs[o]);
    set_name_index (&output_name, o);
    set_name_string (&output_name, output_info->name);
    output = find_output (&output_name);
    if (!output)
    {
        output = add_output ();
        set_name_all (&output->output, &output_name);
    }
    set_output_info (output, res->outputs[o], output_info);
    }
}
/*
 * Test whether 'crtc' can be used for 'output'
 */
static Bool
check_crtc_for_output (crtc_t *crtc, output_t *output)
{
    int        i;
    int        l;
    output_t    *other;
    for (i = 0; i < ncon; i++)
    {
    other = con_outputs[i].output;
    if (other == output)
        continue;
    if (other->mode_info == NULL)
        continue;
    if (other->crtc_info != crtc)
        continue;
    /* see if the output connected to the crtc can clone to this output */
    for (l = 0; l < output->output_info->nclone; l++)
        if (output->output_info->clones[l] == other->output.xid)
        break;
    /* not on the list, can't clone */
    if (l == output->output_info->nclone)
        return False;
    }
    if (crtc->noutput)
    {
    for (i = 0; i < crtc->noutput; i++)
        /* Check if the output is to be turned on */
        if (crtc->outputs[i]->mode_info) {
        /* make sure the state matches */
        if (crtc->mode_info != output->mode_info)
                return False;
        if (crtc->x != output->x)
                return False;
        if (crtc->y != output->y)
                return False;
        if (crtc->rotation != output->rotation)
                return False;
        }
    }
    return True;
}
static crtc_t *
find_crtc_for_output (output_t *output)
{
    int        c;
    for (c = 0; c < output->output_info->ncrtc; c++)
    {
    crtc_t        *crtc;
    crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
    if (!crtc) fatal ("cannot find crtc 0x%x\n", output->output_info->crtcs[c]);
    if (check_crtc_for_output (crtc, output))
        return crtc;
    }
    return NULL;
}
static void
set_positions (void)
{
    Bool    keep_going;
    Bool    any_set;
    int        min_x, min_y;
    int        i;
    for (;;)
    {
    any_set = False;
    keep_going = False;
    for (i = 0; i < ncon; i++)
    {
        output_t    *output = con_outputs[i].output;
        output_t    *relation;
        if (!(output->changes & changes_relation)) continue;
        if (output->mode_info == NULL) continue;
        relation = output->relative_to;
        if (relation->mode_info == NULL)
        {
        output->x = 0;
        output->y = 0;
        output->changes |= changes_position;
        any_set = True;
        continue;
        }
        /*
         * Make sure the dependent object has been set in place
         */
        if ((relation->changes & changes_relation) &&
        !(relation->changes & changes_position))
        {
        keep_going = True;
        continue;
        }
        switch (output->relation) {
        case left_of:
        output->y = relation->y;
        output->x = relation->x - mode_width (output->mode_info, output->rotation);
        break;
        case right_of:
        output->y = relation->y;
        output->x = relation->x + mode_width (relation->mode_info, relation->rotation);
        break;
        case above:
        output->x = relation->x;
        output->y = relation->y - mode_height (output->mode_info, output->rotation);
        break;
        case below:
        output->x = relation->x;
        output->y = relation->y + mode_height (relation->mode_info, relation->rotation);
        break;
        case same_as:
        output->x = relation->x;
        output->y = relation->y;
        }
        output->changes |= changes_position;
        relation->changes |= changes_position;
        any_set = True;
    }
    if (!keep_going)
        break;
    if (!any_set)
        fatal ("loop in relative position specifications\n");
    }
    /*
     * Now normalize positions so the upper left corner of all outputs is at 0,0
     */
    min_x = 32768;
    min_y = 32768;
    for (i = 0; i < ncon; i++)
    {
    output_t    *output = con_outputs[i].output;
    if (output->mode_info == NULL) continue;
    if (output->x < min_x) min_x = output->x;
    if (output->y < min_y) min_y = output->y;
    }
    if (min_x || min_y)
    {
    /* move all outputs */
    for (i = 0; i < ncon; i++)
    {
        output_t    *output = con_outputs[i].output;
        if (output->mode_info == NULL) continue;
        output->x -= min_x;
        output->y -= min_y;
        output->changes |= changes_position;
    }
    }
}
static Bool
set_screen_size (void)
{
    int    i;
    fb_width = fb_height = 0;
    for (i = 0; i < ncon; i++)
    {
        output_t    *output = con_outputs[i].output;
    XRRModeInfo *mode_info = output->mode_info;
    int        x, y, w, h;
    if (!mode_info) continue;
    x = output->x;
    y = output->y;
    w = mode_width (mode_info, output->rotation);
    h = mode_height (mode_info, output->rotation);
    if (x + w > fb_width) fb_width = x + w;
    if (y + h > fb_height) fb_height = y + h;
    }
    if (fb_width > maxWidth || fb_height > maxHeight) {
    if (verbose)
            fprintf (stderr, "screen cannot be larger than %dx%d (desired size %dx%d)\n",
           maxWidth, maxHeight, fb_width, fb_height);
    return False;
    }
    if (fb_width < minWidth) fb_width = minWidth;
    if (fb_height < minHeight) fb_height = minHeight;
    return True;
}
static void
disable_outputs (output_t *outputs)
{
    while (outputs)
    {
    outputs->crtc_info = NULL;
    outputs = outputs->next;
    }
}
/*
 * find the best mapping from output to crtc available
 */
static int
pick_crtcs_score (output_t *outputs)
{
    output_t    *output;
    int        best_score;
    int        my_score;
    int        score;
    crtc_t    *best_crtc;
    int        c;
    if (!outputs)
    return 0;
    output = outputs;
    outputs = outputs->next;
    /*
     * Score with this output disabled
     */
    output->crtc_info = NULL;
    best_score = pick_crtcs_score (outputs);
    if (output->mode_info == NULL)
    return best_score;
    best_crtc = NULL;
    /*
     * Now score with this output any valid crtc
     */
    for (c = 0; c < output->output_info->ncrtc; c++)
    {
    crtc_t        *crtc;
    crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
    if (!crtc)
        fatal ("cannot find crtc 0x%x\n", output->output_info->crtcs[c]);
    /* reset crtc allocation for following outputs */
    disable_outputs (outputs);
    if (!check_crtc_for_output (crtc, output))
        continue;
    my_score = 1000;
    /* slight preference for existing connections */
    if (crtc == output->current_crtc_info)
        my_score++;
    output->crtc_info = crtc;
    score = my_score + pick_crtcs_score (outputs);
    if (score > best_score)
    {
        best_crtc = crtc;
        best_score = score;
    }
    }
    if (output->crtc_info != best_crtc)
    output->crtc_info = best_crtc;
    /*
     * Reset other outputs based on this one using the best crtc
     */
    (void) pick_crtcs_score (outputs);
    return best_score;
}
/*
 * Pick crtcs for any changing outputs that don't have one
 */
static Bool
pick_crtcs (void)
{
    output_t    *output;
    int i;
    /*
     * First try to match up newly enabled outputs with spare crtcs
     */
    for (i = 0; i < ncon; i++)
    {
    output = con_outputs[i].output;
    if (output->mode_info)
    {
        if (output->crtc_info)  {
        if (output->crtc_info->crtc_info->noutput > 0 &&
            (output->crtc_info->crtc_info->noutput > 1 ||
             output != find_output_by_xid (output->crtc_info->crtc_info->outputs[0])))
            break;
        } else {
        output->crtc_info = find_crtc_for_output (output);
        if (!output->crtc_info)
            break;
        else {
            if (verbose)
            fprintf(stderr, "picked crtc 0x%lx for output %d (%s)\n",
                output->crtc_info->crtc.xid, i, output->output_info->name);
        }
        }
    }
    }
    /*
     * Everyone is happy
     */
    if (i == ncon)
    return True;
    /*
     * When the simple way fails, see if there is a way
     * to swap crtcs around and make things work
     */
    for (output = outputs; output; output = output->next)
    output->current_crtc_info = output->crtc_info;
    pick_crtcs_score (outputs);
    for (output = outputs; output; output = output->next)
    {
    if (output->mode_info && !output->crtc_info) {
        if (verbose)
        fprintf (stderr, "cannot find crtc for output %s\n",
            output->output.string);
        return False;
    }
    }
    return True;
}
static Bool
probe_and_check_output_changes (void) {
    XRRScreenResources  *new_res = NULL;
    int     changed = False;
    int  i;
    new_res = XRRGetScreenResources (dpy, root);
    if (!new_res)
        fatal ("could not get screen resources");
    if ((new_res->noutput != res->noutput) || (new_res->nmode != res->nmode) ||
    (new_res->ncrtc != res->ncrtc))
    changed = True;
    else {
    for (i = 0; i < new_res->noutput; i++)
        if (new_res->outputs[i] != res->outputs[i]) {
        changed = True;
        break;
        }
    for (i = 0; i < new_res->nmode; i++)
        if (new_res->modes[i].id != res->modes[i].id) {
        changed = True;
        break;
        }
    for (i = 0; i < new_res->ncrtc; i++) {
        crtc_t  *crtc = NULL;        /* old */
        XRRCrtcInfo *crtc_info = NULL;    /* new */
        crtc = find_crtc_by_xid (res->crtcs[i]);
        crtc_info = XRRGetCrtcInfo (dpy, new_res,
        new_res->crtcs[i]);
        if (!crtc || !crtc_info) {
            changed = True;
            break;
        }
        if (!crtc->mode_info && !find_mode_by_xid (crtc_info->mode))
        continue;
            if ((crtc_info->x != crtc->x) ||
            (crtc_info->y != crtc->y) ||
             (find_mode_by_xid (crtc_info->mode) != crtc->mode_info) ||
            (crtc_info->rotation != crtc->rotation)) {
            changed = True;
            break;
        }
    }
    }
    if (changed) {
    if (res)
        XRRFreeScreenResources(res);
    res = new_res;
    if (verbose)
        fprintf(stderr, "probed: output status changed\n");
    return True;
    }
    if (verbose)
    fprintf(stderr, "probed: no output status change\n");
    return False;
}
static Bool
need_probe (void) {
    struct timeval    cur_time_val;
    long long    cur, prev;
    X_GETTIMEOFDAY(&cur_time_val);
    cur = (long long) cur_time_val.tv_sec * 1000000 + cur_time_val.tv_usec;
    prev =(long long) time_val.tv_sec * 1000000 + time_val.tv_usec;
    if (((cur - prev) < 0) || ((cur - prev) > 5000000))
    return True;
    else
    return False;
}
static int
mode_sort (const void *p1, void *p2)
{
    XRRModeInfo *mi1 = * (XRRModeInfo **) p1;
    XRRModeInfo *mi2 = * (XRRModeInfo **) p2;
    if ((mi1->width == mi2->width) && (mi1->height == mi2->height)) {
    if (mode_refresh(mi1) && mode_refresh(mi2)) {
        if (mode_refresh(mi1) < mode_refresh(mi2))
        return 1;
        if (mode_refresh(mi1) > mode_refresh(mi2))
        return -1;
    } else
            return 0;
    }
    if ((mi1->width == mi2->width) && (mi1->height < mi2->height))
        return 1;
    if ((mi1->width == mi2->width) && (mi1->height > mi2->height))
        return -1;
    if (mi1->width < mi2->width)
        return 1;
    if (mi1->width > mi2->width)
        return -1;
    return 0;
}
static int
output_sort (const void *p1, const void *p2) {
    con_output_t co1 = * (con_output_t *) p1;
    con_output_t co2 = * (con_output_t *) p2;
    int ncrtc1 = co1.output->output_info->ncrtc;
    int ncrtc2 = co2.output->output_info->ncrtc;
    char *name1 = co1.output->output_info->name;
    char *name2 = co2.output->output_info->name;
    if (ncrtc1 == ncrtc2)
    return (strcmp(name1, name2));
    if (ncrtc1 <  ncrtc2)
    return -1;
    return 1;
}
static Bool
get_common_mode(con_output_t *c0, con_output_t *c1, int *m0, int *m1) {
    int        i, j;
    int        i1 = -1, j1 = -1, i2 = -1, j2 = -1;
    int        x, y, w, h;
    output_t    *output = c0->output;
    *m0 = -1;
    *m0 = -1;
    if (!c0 ||!c1 || !c0->smodes || !c1->smodes)
    return False;
    /* first try to find mode with common same size */
    for (i = 0; i < c0->nsmodes; i ++) {
    for (j = 0; j < c1->nsmodes; j ++)
        if ((c0->smodes[i]->width == c1->smodes[j]->width) &&
        (c0->smodes[i]->height == c1->smodes[j]->height)) {
        x = output->x;
        y = output->y;
        w = mode_width (c0->smodes[i], output->rotation);
        h = mode_height (c0->smodes[i], output->rotation);
        if ((x + w <=  maxWidth) && (y + h <= maxHeight)) {
            i1 = i; j1 = j;
            break;
        }
        }
    if ((i1 != -1) && (j1 != -1))
        break;
    }
    if ((i1 == -1) && (j1 == -1))
    return False;
    /* then try to find mode with common id for possible cloning */
    for (i = 0; i < c0->nsmodes; i ++) {
    for (j = 0; j < c1->nsmodes; j ++)
        if (c0->smodes[i] == c1->smodes[j]) {
        x = output->x;
        y = output->y;
        w = mode_width (c0->smodes[i], output->rotation);
        h = mode_height (c0->smodes[i], output->rotation);
        if ((x + w <=  maxWidth) && (y + h <= maxHeight)) {
            i2 = i; j2 = j;
            break;
        }
        }
    if ((i2 != -1) && (j2 != -1))
        break;
    }
    if ((i2 == -1) && (j2 == -1)) {
    *m0 = i1;
    *m1 = j1;
    } else {
    /* use common id if it is not smaller */
    if ((mode_width (c0->smodes[i1], output->rotation) >
        mode_width (c0->smodes[i2], output->rotation)) &&
        (mode_height (c0->smodes[i1], output->rotation) >
        mode_height (c0->smodes[i2], output->rotation))) {
        *m0 = i1;
        *m1 = j1;
    } else {
        *m0 = i2;
        *m1 = j2;
    }
    }
    return True;
}
static XRRModeInfo *
get_largest_mode (con_output_t *c, XRRModeInfo *start_mode) {
    int        i, found = False;
    output_t    *output = c->output;
    for (i = 0; i < c->nsmodes; i++) {
    XRRModeInfo *mode_info = c->smodes[i];
    int     x, y, w, h;
    if (!found && (start_mode != mode_info))
        continue;
    else
        found = True;
    if (mode_info) {
        x = output->x;
            y = output->y;
            w = mode_width (mode_info, output->rotation);
            h = mode_height (mode_info, output->rotation);
        if ((x + w <=  maxWidth) && (y + h <= maxHeight))
        break;
    }
    }
    if (i < c->nsmodes)
    return c->smodes[i];
    else
    fatal("cannot find mode");
}
static Bool
valid_mode(con_output_t *con, XRRModeInfo *mode) {
    int i;
    for (i = 0; i < con->nsmodes; i++)
    if (con->smodes[i] == mode)
        return True;
    return False;
}
static void
do_init (void)
{
    int         i, j;
    output_t    *output;
    /* Initialize con_outputs array */
    for (i = 0; i < MAX_OUTPUT; i++) {
    con_outputs[i].output = NULL;
    con_outputs[i].on = False;
    start_mode[i] = NULL;
    new_mode[i] = NULL;
    }
    ncon = 0;
    dis_ncon = 0;
    init_rotation = RR_Rotate_0;
    init_x = 0;
    init_y = 0;
    get_crtcs ();
    get_outputs ();
    for (output = outputs; output; output = output->next) {
    XRROutputInfo   *output_info = output->output_info;
    if (output_info->connection == RR_Connected) {
        con_outputs[ncon].output = output;
        con_outputs[ncon].nsmodes = 0;
        for (j = 0; j < output_info->nmode; j++) {
        XRRModeInfo *rmode = find_mode_by_xid (output_info->modes[j]);
         con_outputs[ncon].smodes =
            realloc(con_outputs[ncon].smodes,
            (con_outputs[ncon].nsmodes + 1) * sizeof (XRRModeInfo *));
        con_outputs[ncon].smodes[j] = rmode;
        con_outputs[ncon].nsmodes ++;
        }
        /* Sort the modes */
            qsort((void *) con_outputs[ncon].smodes,
        con_outputs[ncon].nsmodes, sizeof(XRRModeInfo *),
        (int (*) (const void *, const void *)) mode_sort);
        if (output_info->crtc) {
        crtc_t      *crtc;
        con_outputs[ncon].on = True;
        for (j = 0; j < output_info->ncrtc; j++) {
            if (output_info->crtcs[j] == output_info->crtc)
                            break;
                    if (j == output_info->ncrtc) {
            if (verbose)
                            fatal ("crtc does not match for output\n");
                    }
        }
        /* set initial mode_info */
        crtc = find_crtc_by_xid (output_info->crtc);
        if (crtc)
            con_outputs[ncon].output->mode_info =
            find_mode_by_xid (crtc->crtc_info->mode);
        }
        else
        con_outputs[ncon].on = False;
        ncon ++;
    } else if (output_info->connection == RR_Disconnected) {
        dis_con_outputs[dis_ncon].output = output;
        dis_ncon ++;
    }
    }
    qsort((void **) con_outputs, ncon,
    sizeof(con_output_t), (int (*) (const void *, const void *)) output_sort);
    if (verbose) {
    fprintf(stderr, "Total connected outputs = %d :\n", ncon);
    for (j = 0; j < ncon; j++) {
        fprintf(stderr, "%d (%s): top mode = %s, rotation = %d, crtcs =", j,
        con_outputs[j].output->output_info->name,
        con_outputs[j].smodes[0]->name,
        con_outputs[j].output->rotation);
        for (i = 0; i < con_outputs[j].output->output_info->ncrtc; i++)
        fprintf(stderr, " 0x%lx", con_outputs[j].output->output_info->crtcs[i]);
        fprintf(stderr, ", using 0x%lx", con_outputs[j].output->output_info->crtc);
        fprintf(stderr, "\n");
    }
    fprintf(stderr, "Total disconnected outputs = %d :\n", dis_ncon);
    for (j = 0; j < dis_ncon; j++) {
        fprintf(stderr, "%d (%s) : number of crtcs %d =", j,
        dis_con_outputs[j].output->output_info->name,
        dis_con_outputs[j].output->output_info->ncrtc);
        for (i = 0; i < dis_con_outputs[j].output->output_info->ncrtc; i++)
        fprintf(stderr, " 0x%lx", dis_con_outputs[j].output->output_info->crtcs[i]);
        fprintf(stderr, ", using 0x%lx", dis_con_outputs[j].output->output_info->crtc);
        fprintf(stderr, "\n");
    }
    }
    i = con_outputs[2].on * 4 + con_outputs[1].on * 2 + con_outputs[0].on;
    if ((i == 1) || (i == 2) || (i == 4)) {
    use_init_pos = True;
    j = i >> 1;
    /* remember position and mode info in single state */
        start_mode[j] = con_outputs[j].output->mode_info;
    init_rotation = con_outputs[j].output->rotation;
    init_x = con_outputs[j].output->x;
    init_y = con_outputs[j].output->y;
    } else
    use_init_pos = False;
    if ((ncon != 2) || (start < 3))
    start = i;
    if ((ncon < 1) || (ncon > 3)) {
    if ((ncon < 1) && verbose)
        fprintf (stderr, "warn: no connection\n");
    else if ((ncon > 3) && verbose)
        fprintf (stderr, "warn: too many (more than 3) connections: %d: can't switch\n", ncon);
    do_not_switch = True;
    }
    did_init = True;
    return;
}
static int
grab_key (Display *dpy, int keysym, unsigned int modifier,
    Window grab_window)
{
    char    msg[256];
    int keycode = XKeysymToKeycode(dpy, keysym);
    if (keycode ==  NoSymbol)
    fatal ("grab_key: keycode not defined for keysym 0x%x\n", keysym);
    had_error = 0;
    prev_handler = XSetErrorHandler (cur_handler);
    if (!testrun) {
        XGrabKey(dpy,
        keycode,
        modifier,
        root, True, GrabModeAsync, GrabModeAsync);
        XSync (dpy, False);
    }
    XSetErrorHandler (prev_handler);
    if (had_error) {
    XGetErrorText (dpy, had_error, msg, sizeof (msg));
    fatal ("XGrabKey: %s\n", msg);
    }
    if (verbose)
    fprintf(stderr, "keycode to grab: %d\n", keycode);
    return keycode;
}
static Bool
do_switch (void)
{
    int     i, j;
    int        single;
    int        save = -1;
    if (ncon <= 0)
    return True;
    for (i = 0; i < ncon; i++) {
    output_t    *output = con_outputs[i].output;
    new_mode[i] = NULL;
    output->relation = same_as;
    output->relative_to = NULL;
    if (use_init_pos) {
        output->x = init_x;
        output->y = init_y;
        output->rotation = init_rotation;
    } else {
        output->x = 0;
        output->y = 0;
    }
    }
    if (ncon == 2) {
    if (!nosideview) {
        if (++start > 5)    start = 1;
    }
    else {
        if (++start > 3)    start = 1;
    }
    if (verbose)
        fprintf(stderr, "current state = %d\n", start);
    if (start >= 3) {
        int m0, m1;
            if (get_common_mode(&con_outputs[0], &con_outputs[1], &m0, &m1)) {
        new_mode[0] = con_outputs[0].smodes[m0];
                new_mode[1] = con_outputs[1].smodes[m1];
        } else {
        new_mode[0] = get_largest_mode (&con_outputs[0],
            con_outputs[0].smodes[0]);
        new_mode[1] = get_largest_mode (&con_outputs[1],
            con_outputs[1].smodes[0]);
        }
    } else {
        if (start_mode[start -1] && valid_mode(&con_outputs[start -1],
        start_mode[start -1]))
            new_mode[start -1] = start_mode[start -1];
        else {
            if (con_outputs[start -1].smodes[0])
            new_mode[start -1] =
            get_largest_mode (&con_outputs[start-1],
            con_outputs[start -1].smodes[0]);
        }
    }
    }
    if (ncon == 3) {
    if (++start > 6)    start = 1;
    if (verbose)
        fprintf(stderr, "current state = %d\n", start);
    if ((start == 1) || (start == 2) || (start == 4)) {
        single = 1;
        i = start >> 1;
        j = 0;
    }
    else {
        single = 0;
        if (start > 4)
        j = 2;
        else
        j = 1;
        if (start > 5)
        i = 1;
        else
        i = 0;
    }
    if (single) {
        if (start_mode[i] && valid_mode(&con_outputs[i], start_mode[i]))
        new_mode[i] = start_mode[i];
        else {
            if (con_outputs[i].smodes[0])
            new_mode[i] = get_largest_mode (&con_outputs[i],
            con_outputs[i].smodes[0]);
        }
    }
    else {
        int m0, m1;
            if (get_common_mode(&con_outputs[i], &con_outputs[j], &m0, &m1)) {
        new_mode[i] = con_outputs[i].smodes[m0];
        new_mode[j] = con_outputs[j].smodes[m1];
            } else {
        new_mode[i] = get_largest_mode (&con_outputs[i],
            con_outputs[i].smodes[0]);
        new_mode[j] = get_largest_mode (&con_outputs[j],
            con_outputs[j].smodes[0]);
        }
    }
    }
    if (ncon == 1) {
    if (start_mode[0] && valid_mode(&con_outputs[0], start_mode[0]))
        new_mode[0] = start_mode[0];
    else {
        if (con_outputs[0].smodes[0])
        new_mode[0] = get_largest_mode (&con_outputs[0],
            con_outputs[0].smodes[0]);
    }
    }
    /* Set mode */
    for (i = 0; i < ncon; i++) {
        output_t    *output;
        output = con_outputs[i].output;
    if (new_mode[i]) {
        if ((!output->mode_info) || (output->mode_info != new_mode[i])) {
            output->mode_info = new_mode[i];
            con_outputs[i].on = True;
        if (verbose)
            fprintf(stderr, "set output %d (%s) to mode %s rotation %d\n", i,
            con_outputs[i].output->output_info->name,
            con_outputs[i].output->mode_info->name,
            con_outputs[i].output->rotation);
            }
    } else if (con_outputs[i].on ) {
        if (!need_off_deferred) {
        output->mode_info = NULL;
        con_outputs[i].on = False;
        if (verbose)
            fprintf(stderr, "turn off output %d (%s) \n",
            i, con_outputs[i].output->output_info->name);
        } else
        save = i;
    }
    }
    if ((ncon == 2) && (start >= 4)) {
    if (start == 4) {
        con_outputs[1].output->relative_to = con_outputs[0].output;
        con_outputs[1].output->relation = right_of;
        con_outputs[1].output->changes = changes_relation;
        con_outputs[0].output->changes = 0;
    }
    else if (start == 5) {
        con_outputs[0].output->relative_to = con_outputs[1].output;
        con_outputs[0].output->relation = right_of;
        con_outputs[0].output->changes = changes_relation;
        con_outputs[1].output->changes = 0;
    }
    set_positions();
    }
    if (!set_screen_size ())
    return False;
    /* reset crtcs before allocation */
    reset_crtcs_for_outputs();
    if (!did_init)
    get_crtcs();
    if (!pick_crtcs()) {
    if (verbose)
        fprintf(stderr, "pick_crtcs failed\n");
    return True;
    }
    set_crtcs ();
    apply();
    if (need_off_deferred && (save != -1)) {
    /* Now, take the deferred output off */
    output_t    *output;
    crtc_t      *crtc;
    Status      s;
    output = con_outputs[save].output;
    output->mode_info = NULL;
    con_outputs[save].on = False;
    if (verbose)
        fprintf(stderr, "turn off output %d (%s) \n",
        save, con_outputs[save].output->output_info->name);
    crtc = output->crtc_info;
    s = crtc_disable (crtc);
    if (s != RRSetConfigSuccess)
        panic (s, crtc);
    }
    XSync (dpy, False);
    did_init = False;
    return True;
}
static Bool
do_toggle (void)
{
    Atom        atom;
    XEvent        xev;
    int            ret;
    atom = XInternAtom (dpy, "DISPLAYSWITCH_DAEMON", True);
    if (!atom) {
    fprintf(stderr, "dispswitch daemon not running\n");
    return False;
    }
    win = XGetSelectionOwner (dpy, atom);
    if (!win) {
    fprintf(stderr, "dispswitch: No owner of dispswitch daemon is found\n");
    return False;
    }
    bzero (&xev, sizeof (XEvent));
    xev.xkey.type = KeyPress;
    xev.xkey.send_event = True;
    xev.xkey.display = dpy;
    /* Any keycode */
    xev.xkey.keycode = 71;
    /*
     * Send another instance of dispswitch (a daemon) an event to
     * request a switch
     */
    ret = XSendEvent(dpy, win, False, KeyPressMask, &xev);
    XFlush(dpy);
    if (!ret)
    fprintf(stderr, "dispswitch: XSendEvent error\n");
    return (!ret);
}
int
main (int argc, char **argv)
{
    char    *display_name = NULL;
    int        major, minor;
    int        i;
    char    msg[256];
    XEvent  ev;
    unsigned int    modifier = 0;
    Bool    key_given = False;
    Bool    mod_given = False;
    int        keysym = 0, toggle = False, listen = False;
    Atom    atom;
    program_name = argv[0];
    for (i = 1; i < argc; i++) {
    if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
        if (++i>=argc) usage ();
            display_name = argv[i];
        continue;
        }
    if (!strcmp ("-key", argv[i]) || !strcmp ("-k", argv[i])) {
        if (++i>=argc) usage ();
        if ((keysym = XStringToKeysym(argv[i])) == NoSymbol) {
        fprintf(stderr, "invalid keysym: -key %s\n", argv[i]);
        usage();
        }
        key_given = True;
        continue;
    }
    if (!strcmp ("-mod", argv[i]) || !strcmp ("-m", argv[i])) {
        int     j;
        char     *s, *p, *q;
        int        end = 0;
        if (++i>=argc) usage ();
        s = strdup (argv[i]);
        if (!s) {
        if (verbose)
            fprintf(stderr, "modifier failed, will use default modifier\n");
         continue;
        }
        while (*s == ' ') s++;
        p = s + strlen(s) - 1;
        while (*p == ' ') *p-- = 0;
        q = s;
        for (; ;) {
            if (p = strchr(s, '+')) {
            *p = ' ';
            while ((p > s) && (*(p-1) == ' ')) p--;
            *p = 0;
        }
        else
            end = 1;
            for (j = 0; j < MAX_MODIFIERS; j++) {
                 if (!strcmp(mod_key_table[j].modname, s)) {
            modifier |= mod_key_table[j].mod;
            break;
            }
        }
           if (j == MAX_MODIFIERS) {
            fprintf(stderr, "invalid modifier: -mod %s\n", q);
             usage();
        }
        if (end)
            break;
        else {
            s = ++p;
            while (*s == ' ') s++;
        }
        }
        mod_given = True;
        free (q);
        continue;
        }
    if (!strcmp ("-nosideview", argv[i])) {
        nosideview = True;
        continue;
        }
    if (!strcmp ("-verbose", argv[i]) || !strcmp ("-v", argv[i])) {
        verbose = True;
        continue;
        }
    if (!strcmp ("-testrun", argv[i])) {
        testrun = True;
        verbose = True;
        continue;
        }
    if (!strcmp ("-toggle", argv[i]) || !strcmp ("-t", argv[i])) {
        toggle = True;
        continue;
        }
    if (!strcmp ("-listen", argv[i]) || !strcmp ("-l", argv[i])) {
        listen = True;
        continue;
        }
    usage();
    }
    dpy = XOpenDisplay (display_name);
    if (dpy == NULL)
    fatal ("can't open display %s\n", XDisplayName(display_name));
    screen = DefaultScreen (dpy);
    root = RootWindow (dpy, screen);
    if (!XRRQueryVersion (dpy, &major, &minor))
    fatal ("randr extension missing\n");
    if ((major <= 1) &&  (major != 1 || minor < 2))
    fatal ("wrong randr version: %d.%d\n", major, minor);
    if (toggle)
    exit (do_toggle());
    /*
     * Create an atom, a trivial window, and make it selection owner.
     * Ready to accept a client event request for switch
     */
    atom = XInternAtom(dpy, "DISPLAYSWITCH_DAEMON", False);
    if (!atom) {
    if (verbose)
        fprintf(stderr, "cannot create Atom\n");
    }
    else {
    if (XGetSelectionOwner (dpy, atom)) {
        if (verbose)
        fprintf(stderr, "dispswitch daemon is already running, quit\n");
        exit (1);
    }
    win = XCreateSimpleWindow(dpy, root, 0, 0, 10, 10, 0, 10, 0);
    if (!win) {
        if (verbose)
        fprintf(stderr, "cannot create window\n");
    }
    else {
        XSetSelectionOwner(dpy, atom, win, CurrentTime);
        if (XGetSelectionOwner(dpy, atom) != win) {
        if (verbose)
            fprintf(stderr, "set selection owner failed\n");
        } else
        XSelectInput(dpy, win, KeyPressMask);
    }
    }
    /* set default key and modifier if not given in command */
    if (!key_given)
    keysym  = XStringToKeysym ("F5");
    if (!mod_given)
    modifier = ShiftMask;
    if (!listen)
    cur_keycode = grab_key (dpy, keysym, modifier, root);
    XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight,
                           &maxWidth, &maxHeight);
    fb_width_mm = DisplayWidthMM (dpy, screen);
    fb_height_mm = DisplayHeightMM (dpy, screen);
    dpi = (25.4 * DisplayHeight (dpy, screen)) / DisplayHeightMM(dpy, screen);
    res = XRRGetScreenResources (dpy, root);
    if (!res)
    fatal ("could not get screen resources\n");
    if (res->ncrtc < 2)
    fatal ("too few crtcs: %d\n", res->ncrtc);
    do_init();
    X_GETTIMEOFDAY(&time_val);
    for(;;)
    {
    need_off_deferred = False;
    if (testrun) {
        usleep(4000000);
        fprintf(stderr, "\n");
    } else
        XNextEvent(dpy, &ev);
    if (!listen && !testrun && (ev.type == MappingNotify) &&
        ((ev.xmapping.request == MappingKeyboard) ||
        (ev.xmapping.request == MappingModifier))) {
        /* keyboard/modifier mapping changed */
        if (verbose)
        fprintf(stderr, "\nkeyboard/modifier mapping changed ...\n");
        XUngrabKey(dpy, cur_keycode, modifier, root);
        cur_keycode = grab_key (dpy, keysym, modifier, root);
    }
    if (testrun || (ev.type == KeyPress)) {
        if (verbose)
        fprintf(stderr, "\na key press event was grabbed ...\n");
        do_not_switch = False;
        if (testrun || need_probe()) {
        /* Too long since last switch, need to check output changes */
        if (probe_and_check_output_changes ()) {
            output_t    *output, *next;
            output = outputs;
            while (output) {
            if (output->output_info)
                XRRFreeOutputInfo (output->output_info);
            if (output->crtc_info && output->crtc_info->outputs) {
                free(output->crtc_info->outputs);
                output->crtc_info->outputs = NULL;
            }
            next = output->next;
            free(output);
            output = next;
            }
            outputs = NULL;
            outputs_tail = &outputs;
            for (i = 0; i < ncon; i++) {
            con_outputs[i].output = NULL;
            con_outputs[i].on = False;
            if (con_outputs[i].smodes) {
                free(con_outputs[i].smodes);
                con_outputs[i].smodes = NULL;
            }
            con_outputs[i].nsmodes = 0;
            }
            do_init();
        } else if (ncon == 1)
            do_not_switch = True;
        } else if (ncon == 1)
        do_not_switch = True;
            if (!do_not_switch) {
        if ((ncon == 2) && (start == 1))
            /*
             * Workaround for intel based graphics: in switching from
             * LVDS to VGA, off on LVDS needs to be deferred.
             */
            need_off_deferred = True;
            if (!do_switch()) {
            if ((ncon == 2) && (start == 4)) {
            start = 5;
            if (verbose)
                fprintf(stderr, "too small screen, skipping side view\n");
            (void) do_switch();
            }
        }
        }
        X_GETTIMEOFDAY(&time_val);
    }
    }
}
components/x11/dispswitch/src/dispswitch.man
New file
@@ -0,0 +1,102 @@
'\" t
.\"
.\" Copyright 2001 Keith Packard
.\"
.\" 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 Keith Packard not be used in
.\" advertising or publicity pertaining to distribution of the software without
.\" specific, written prior permission.  Keith Packard makes no
.\" representations about the suitability of this software for any purpose.  It
.\" is provided "as is" without express or implied warranty.
.\"
.\" KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
.\" EVENT SHALL KEITH PACKARD 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 (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
.\"
.\" Permission is hereby granted, free of charge, to any person obtaining a
.\" copy of this software and associated documentation files (the "Software"),
.\" to deal in the Software without restriction, including without limitation
.\" the rights to use, copy, modify, merge, publish, distribute, sublicense,
.\" and/or sell copies of the Software, and to permit persons to whom the
.\" Software is furnished to do so, subject to the following conditions:
.\"
.\" The above copyright notice and this permission notice (including the next
.\" paragraph) shall be included in all copies or substantial portions of the
.\" Software.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
.\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
.\" THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
.\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
.\" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
.\" DEALINGS IN THE SOFTWARE.
.\"
.\"
.TH DISPSWITCH 1
.SH NAME
dispswitch \- Display Device Switch
.SH SYNOPSIS
.B "/usr/bin/dispswitch"
[\-display \fIdisplay\fP]
[\-key \fIkeysym\fP]
[\-mod \fImodifier\fP]
[\-help]
[\-verbose]
[\-nosideview]
[\-testrun]
.SH DESCRIPTION
.I Dispswitch
uses hotkey to switch/rotate on/off of display devices up to 3 devices. Side-by-side views are included when two devices are connected. It works on systems where both server and driver support RandR version 1.2 (or above).
User can define a hotkey with -key and -mod options (see below), the default is "Shift + F5".
If a key stroke is hit 5 seconds or longer after the previous switch, display devices are re-probed so that any changes such as adding or removing devices, can be detected and adapted to.
If a new display device is added whose mode size is larger than the one with which X server is started, or a side-by-side view is switched into that needs a larger mode to cover both screens, a config file specifying larger virtual screen size (Virtual field in Screen Section) will be needed during X server startup. Otherwise the larger mode will not be realized, or the side-by-side view will be skipped.
.IP \-help
Print out a summary of the usage and exit.
.IP "\-verbose or -v"
Print out debug messages when run.
.IP \-nosideview
Skip side-by-side views in two devices rotating.
.IP \-testrun
Switch/rotate display device states repeatedly without hotkey strokes.
.IP "\-key <keysym> or -k <keysym>"
Define the keysym of hotkey to be <keysym>, which can be any entry defined in
defined in /usr/include/X11/keysymdef.h, with prefix XK_ removed, such as F5, F8, Escape.
.IP "\-mod <modifier> or -m <modifier>"
Define the modifier of hotkey to be <modifier>. <modifier> is any or combination of modifiers on your system. Run
.BR xmodmap (1)
to find all available modifiers on your system. They can be none, shift, control, mod1, mod3, mod4, mod5, any.
.SH
Examples:
dispswitch -key Escape -mod shift        defines hotkey to be 'shift + Esc'
.sp
dispswitch -key F2 -mod "shift+control"     defines hotkey to be 'shift + control + F2'
.\" Begin Sun update
.SH "ATTRIBUTES"
See \fBattributes\fR(7) for descriptions of the following attributes:
.sp
.TS
allbox;
cw(2.750000i)| cw(2.750000i)
lw(2.750000i)| lw(2.750000i).
ATTRIBUTE TYPE    ATTRIBUTE VALUE
Availability    pkg:/x11/x11-server-utilities
Interface Stability    Volatile
.TE
.sp
.\" End Sun update
components/x11/dispswitch/src/dispswitch.o
Binary files differ
components/x11/dispswitch/src/gnome-dispswitch.desktop
New file
@@ -0,0 +1,10 @@
[Desktop Entry]
Encoding=UTF-8
Name=Display Switch Daemon
Comment=Handles switching of displays devices
Icon=display
Exec=/usr/bin/dispswitch
Terminal=false
Type=Application
Categories=
X-GNOME-Autostart-enabled=true
components/x11/xf86-input-hotkey/Makefile
New file
@@ -0,0 +1,70 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2015 Alexander Pyhalov
#
include ../../../make-rules/shared-macros.mk
COMPONENT_NAME= xf86-input-hotkey
COMPONENT_SRC= src
COMPONENT_VERSION= 0.5.11
COMPONENT_REVISION= 1
COMPONENT_SUMMARY= xf86-input-hotkey: ACPI hotkey input driver for the Xorg server
COMPONENT_PROJECT_URL = https://hg.java.net/hg/solaris-x11~x-s12-clone
COMPONENT_CLASSIFICATION= Drivers/Other Peripherals
COMPONENT_LICENSE = MIT
COMPONENT_LICENSE_FILE = xf86-input-hotkey.license
COMPONENT_FMRI = x11/server/xorg/driver/xorg-input-hotkey
include $(WS_TOP)/make-rules/justmake.mk
include $(WS_TOP)/make-rules/ips.mk
SERVERMOD_SUBDIR.64=/$(MACH64)
SERVERMOD_SUBDIR=$(SERVERMOD_SUBDIR.$(BITS))
X11_SERVERMODS_DIR=/usr/lib/xorg/modules
CPPFLAGS += -I/usr/include/xorg
CPPFLAGS += -I/usr/include/pixman-1
COMPONENT_COMMON_ENV = CC=$(CC)
COMPONENT_COMMON_ENV += CFLAGS="$(CFLAGS) --std=gnu99"
COMPONENT_COMMON_ENV += CPPFLAGS="$(CPPFLAGS)"
COMPONENT_COMMON_ENV += LDFLAGS="$(LDFLAGS)"
COMPONENT_INSTALL_ARGS += MODULEDIR=$(X11_SERVERMODS_DIR)
COMPONENT_INSTALL_ARGS += ARCHLIBSUBDIR=$(SERVERMOD_SUBDIR)
COMPONENT_BUILD_ENV += $(COMPONENT_COMMON_ENV)
COMPONENT_INSTALL_ENV += INSTALL=$(INSTALL)
COMPONENT_POST_BUILD_ACTION = $(TOUCH) $(BUILD_DIR)
download:
clobber: clean
$(SOURCE_DIR)/.prep:
    $(TOUCH) $@
clean::
    $(RM) $(SOURCE_DIR)/.prep
$(BUILD_32_and_64):    Makefile
build: $(BUILD_32_and_64)
install: $(INSTALL_32_and_64)
test: $(NO_TESTS)
REQUIRED_PACKAGES += system/library
components/x11/xf86-input-hotkey/manifests/sample-manifest.p5m
New file
@@ -0,0 +1,26 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2016 <contributor>
#
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification value="$(COMPONENT_CLASSIFICATION)"
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
file path=usr/lib/xorg/modules/input/$(MACH64)/hotkey_drv.so
file path=usr/lib/xorg/modules/input/hotkey_drv.so
components/x11/xf86-input-hotkey/src/Makefile
New file
@@ -0,0 +1,39 @@
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
SRCS = hotkey.c
OBJS = $(SRCS:.c=.o)
REQLIBS = -lsysevent
MODULEDIR = /lib/modules
DRVDIR = /input
INSTDIR = $(DESTDIR)$(PREFIX)$(MODULEDIR)$(DRVDIR)$(ARCHLIBSUBDIR)
hotkey_drv.so: $(OBJS)
    $(CC) -o $@ $(LDFLAGS) -shared $(OBJS) $(REQLIBS)
.c.o:    Makefile ../../Makefile
    $(CC) -fpic -DPIC $(CFLAGS) $(CPPFLAGS) -c $<
install: hotkey_drv.so
    mkdir -p $(INSTDIR)
    $(INSTALL) hotkey_drv.so $(INSTDIR)/hotkey_drv.so
components/x11/xf86-input-hotkey/src/config.h
New file
@@ -0,0 +1,70 @@
/* config.h.  Generated from config.h.in by configure.  */
/* config.h.in.  Generated from configure.ac by autoheader.  */
#include "xorg-server.h"
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Name of package */
#define PACKAGE "xf86-input-hotkey"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "https://bugs.freedesktop.org/enter_bug.cgi?product=xorg"
/* Define to the full name of this package. */
#define PACKAGE_NAME "xf86-input-hotkey"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "xf86-input-hotkey 1.0.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "xf86-input-hotkey"
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.0.0"
/* Major version of this package */
#define PACKAGE_VERSION_MAJOR 1
/* Minor version of this package */
#define PACKAGE_VERSION_MINOR 0
/* Patch version of this package */
#define PACKAGE_VERSION_PATCHLEVEL 0
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "1.0.0"
/* Flag */
#define SUNSOFT 1
components/x11/xf86-input-hotkey/src/hotkey.c
New file
@@ -0,0 +1,351 @@
/* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include "config.h"
#include <xorg-server.h>
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86Xinput.h"
#include "xf86_OSproc.h"
#include <X11/XF86keysym.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <libsysevent.h>
#include <xkbsrv.h>
static int HkeyPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
static void HkeyUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
_X_EXPORT InputDriverRec HKEY = {
        1,
        "hotkey",
        NULL,
        HkeyPreInit,
        HkeyUnInit,
        NULL,
        0
};
static struct {
    const char    *sub_class;
    KeySym    keysym;
} sub_to_keysym_table [] = {
    { "ESC_acpiev_display_switch",     XF86XK_Display },
    { "ESC_acpiev_sleep",         XF86XK_Sleep },
    { "ESC_acpiev_screen_lock",        XF86XK_ScreenSaver },
    { NULL,                NoSymbol }
};
#define    EC_ACPIEV            "EC_acpiev"
#define HOTKEY_KEYSYM_ROOT        (XF86XK_Display & 0xFFFFFF00)
static sysevent_handle_t    *hotkey_event_entry;
static int             hotkey_event_fd[2] = {-1, -1};
static void
hotkey_event_handler(sysevent_t *ev)
{
    int        i;
    char    buf;
    char    *subclass;
    KeySym    keysym = 0;
    subclass = sysevent_get_subclass_name(ev);
    for (i = 0; sub_to_keysym_table[i].sub_class != NULL; i++)
    if (!strcmp (sub_to_keysym_table[i].sub_class, subclass)) {
        keysym = sub_to_keysym_table[i].keysym;
        break;
    }
    if (sub_to_keysym_table[i].sub_class == NULL)
    return;
    buf = keysym - HOTKEY_KEYSYM_ROOT;
    write(hotkey_event_fd[1], &buf, 1);
}
static  Bool
map_init(DeviceIntPtr device)
{
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
    if (!InitKeyboardDeviceStruct(device, NULL, NULL, NULL)) {
    xf86Msg(X_WARNING, "hotkey map_init failed\n");
    return FALSE;
    }
#else
    KeySymsRec  keySyms;
    CARD8    *modMap;
    keySyms.minKeyCode = inputInfo.keyboard->key->curKeySyms.minKeyCode;
    keySyms.maxKeyCode = inputInfo.keyboard->key->curKeySyms.maxKeyCode;
    keySyms.mapWidth = inputInfo.keyboard->key->curKeySyms.mapWidth;
    keySyms.map = (KeySym *)xcalloc(sizeof(KeySym),
    (keySyms.maxKeyCode - keySyms.minKeyCode + 1) * keySyms.mapWidth);
    if (!keySyms.map) {
    xf86Msg (X_WARNING, "Couldn't allocate hotkey core keymap\n");
    return FALSE;
    }
    modMap = (CARD8 *)xcalloc(1, MAP_LENGTH);
    if (!modMap) {
    xf86Msg (X_WARNING, "Couldn't allocate hotkey modifier keymap\n");
    return FALSE;
    }
#ifdef XKB
    if (!noXkbExtension) {
    XkbComponentNamesRec names;
    bzero(&names, sizeof(names));
    XkbInitKeyboardDeviceStruct(device, &names, &keySyms, modMap, NULL, NULL);
    } else
#endif
    /* FIXME Our keymap here isn't exactly useful. */
    InitKeyboardDeviceStruct((DevicePtr)device, &keySyms, modMap, NULL, NULL);
    xfree(keySyms.map);
    xfree(modMap);
#endif
    return TRUE;
}
static void
hotkey_events_fini(void)
{
    sysevent_unsubscribe_event (hotkey_event_entry, EC_ACPIEV);
    sysevent_unbind_handle (hotkey_event_entry);
    hotkey_event_entry = NULL;
    xf86Msg(X_CONFIG, "hotkey_events_fini: succeeded\n");
}
static    Bool
hotkey_events_init(DeviceIntPtr device) {
    const char    *subclass_list[] = {EC_SUB_ALL};
    hotkey_event_entry = sysevent_bind_handle (hotkey_event_handler);
    if (hotkey_event_entry == NULL) {
    xf86Msg(X_WARNING,
        "hotkey_events_init: sysevent_bind_handle failed: with errno = %d\n" , errno);
    return FALSE;
    }
    else {
    if (sysevent_subscribe_event(hotkey_event_entry, EC_ACPIEV, subclass_list, 1)
        != 0) {
        sysevent_unbind_handle(hotkey_event_entry);
        hotkey_event_entry = NULL;
        xf86Msg(X_CONFIG, "hotkey_events_init: sysevent_subscribe_event failed\n");
        return FALSE;
    }
    }
    return  TRUE;
}
static void
hotkey_read_input(InputInfoPtr pInfo)
{
    unsigned char    buf;
    KeySym    keysym = NoSymbol;
    KeyCode    keycode = 0;
    KeySymsPtr    curKeySyms;
    DeviceIntPtr    dev = pInfo->dev;
    int         i;
    if (read (pInfo->fd, &buf, 1 ) == 1)
    keysym = buf + HOTKEY_KEYSYM_ROOT;
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
    if (dev->master)
    curKeySyms = XkbGetCoreMap(dev->master);
    else
    curKeySyms = XkbGetCoreMap(inputInfo.keyboard);
#else
    if (dev->master)
    curKeySyms = &dev->master->key->curKeySyms;
    else
    curKeySyms = &inputInfo.keyboard->key->curKeySyms;
#endif
    for (i = curKeySyms->minKeyCode; i <= curKeySyms->maxKeyCode; i++) {
    if (curKeySyms->map[(i - curKeySyms->minKeyCode) * curKeySyms->mapWidth]
        == keysym) {
        keycode = i;
        break;
    }
    }
    if (!keycode)
    xf86MsgVerb(X_WARNING, 0, "Hotkey keysym %x not mapped\n", (int) keysym);
    else {
    xf86MsgVerb(X_INFO, 3, "Posting keycode %d for keysym %x on device %s\n",
        keycode, (int) keysym, pInfo->dev->name);
    xf86PostKeyboardEvent(pInfo->dev, keycode, TRUE);
    xf86PostKeyboardEvent(pInfo->dev, keycode, FALSE);
    }
}
static int
HkeyProc(DeviceIntPtr device, int what)
{
    InputInfoPtr pInfo = device->public.devicePrivate;
    char     *s;
    DeviceIntPtr mdev;
    int        blocked;
    switch (what) {
         case DEVICE_INIT:
        if (!map_init(device)) {
        xf86Msg(X_WARNING, "HkeyProc: map_init failed\n");
        return (!Success);
        }
        /*
         * Block SIGIO so the new libsysevent/door threads created will
         * mask SIGIO. See 6875743.
         */
        blocked = xf86BlockSIGIO();
        if (hotkey_events_init(device)) {
        if (pipe (hotkey_event_fd) == -1) {
            xf86Msg(X_WARNING,
            "hotkey_events_init: pipe open failed with errno %d\n", errno);
            hotkey_events_fini();
                xf86UnblockSIGIO(blocked);
            return (!Success);
        } else {
            pInfo->fd = hotkey_event_fd[0];
            xf86Msg(X_CONFIG, "hotkey_events_init and pipe open succeeded\n");
                }
            } else {
        xf86Msg(X_WARNING, "hotkey_events_init failed\n");
            xf86UnblockSIGIO(blocked);
        return (!Success);
        }
        xf86UnblockSIGIO(blocked);
            device->public.on = FALSE;
        break;
    case DEVICE_ON:
            if (device->public.on)
            break;
        xf86FlushInput(pInfo->fd);
        AddEnabledDevice(pInfo->fd);
        if (device->master)
        dixSetPrivate(&device->master->devPrivates,
            HotkeyMapDevicePrivateKey, device);
        device->public.on = TRUE;
        break;
    case DEVICE_CLOSE:
        if (pInfo->fd != -1)
        RemoveEnabledDevice(pInfo->fd);
        close(hotkey_event_fd[0]);
        close(hotkey_event_fd[1]);
        hotkey_events_fini();
        break;
    case DEVICE_OFF:
        if (!device->public.on)
        break;
        if (pInfo->fd != -1)
        RemoveEnabledDevice(pInfo->fd);
        if (device->master)
        dixSetPrivate(&device->master->devPrivates,
            HotkeyMapDevicePrivateKey, NULL);
            device->public.on = FALSE;
        break;
    }
    return (Success);
}
static int
HkeyPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
{
    /* Initialize the InputInfoRec. */
    pInfo->type_name = XI_KEYBOARD;
    pInfo->device_control = HkeyProc;
    pInfo->read_input = hotkey_read_input;
    pInfo->fd = -1;
    pInfo->flags = XI86_ALWAYS_CORE;
    return Success;
}
static void
HkeyUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
{
    xf86DeleteInput(pInfo, 0);
}
static void
HkeyUnplug(pointer p)
{
}
static pointer
HkeyPlug(pointer module, pointer options, int *errmaj, int *errmin)
{
    static Bool Initialised = FALSE;
    if (!Initialised)
        Initialised = TRUE;
    xf86AddInputDriver(&HKEY, module, 0);
    return module;
}
static XF86ModuleVersionInfo HkeyVersionRec = {
    "hotkey",
    MODULEVENDORSTRING,
    MODINFOSTRING1,
    MODINFOSTRING2,
    XORG_VERSION_CURRENT,
    1, 0, 0,
    ABI_CLASS_XINPUT,
    ABI_XINPUT_VERSION,
    MOD_CLASS_XINPUT,
    {0, 0, 0, 0}                /* signature, to be patched into the file by */
                                /* a tool */
};
_X_EXPORT XF86ModuleData hotkeyModuleData = {
    &HkeyVersionRec,
    HkeyPlug,
    HkeyUnplug
};
components/x11/xf86-input-hotkey/xf86-input-hotkey.license
New file
@@ -0,0 +1,20 @@
Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
components/x11/xf86-input-hotkey/xorg-input-hotkey.p5m
New file
@@ -0,0 +1,25 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2015 Alexander Pyhalov
#
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification value="$(COMPONENT_CLASSIFICATION)"
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
file path=usr/lib/xorg/modules/input/$(MACH64)/hotkey_drv.so
file path=usr/lib/xorg/modules/input/hotkey_drv.so