aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw')
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr.c2
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr.h1
-rw-r--r--xorg-server/hw/kdrive/ephyr/hostx.c11
-rw-r--r--xorg-server/hw/kdrive/ephyr/hostx.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86AutoConfig.c1
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2ext.c3
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/Makefile.am3
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/dri2.c2
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/driver.c104
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/driver.h15
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c337
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h33
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c134
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h45
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/present.c228
-rw-r--r--xorg-server/hw/xfree86/drivers/modesetting/vblank.c28
-rw-r--r--xorg-server/hw/xfree86/os-support/solaris/sun_init.c33
-rw-r--r--xorg-server/hw/xfree86/os-support/xf86_OSlib.h5
-rw-r--r--xorg-server/hw/xwayland/xwayland-glamor.c3
-rw-r--r--xorg-server/hw/xwayland/xwayland-input.c7
-rw-r--r--xorg-server/hw/xwin/InitOutput.c4
-rw-r--r--xorg-server/hw/xwin/XWin.rc1
-rw-r--r--xorg-server/hw/xwin/man/XWin.man6
-rw-r--r--xorg-server/hw/xwin/winclipboard/internal.h14
-rw-r--r--xorg-server/hw/xwin/winclipboard/thread.c56
-rw-r--r--xorg-server/hw/xwin/winclipboard/winclipboard.h2
-rw-r--r--xorg-server/hw/xwin/winclipboard/wndproc.c227
-rw-r--r--xorg-server/hw/xwin/winclipboard/xevents.c175
-rw-r--r--xorg-server/hw/xwin/winclipboard/xwinclip.c7
-rw-r--r--xorg-server/hw/xwin/winclipboard/xwinclip.man3
-rw-r--r--xorg-server/hw/xwin/winclipboardwrappers.c6
-rw-r--r--xorg-server/hw/xwin/winprocarg.c27
-rw-r--r--xorg-server/hw/xwin/winresource.h1
-rw-r--r--xorg-server/hw/xwin/wintrayicon.c19
-rw-r--r--xorg-server/hw/xwin/winwndproc.c6
35 files changed, 1060 insertions, 491 deletions
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c
index 93a48a9cd..907bbebae 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyr.c
@@ -1292,7 +1292,7 @@ ephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
if (p > max)
max = p;
- hostx_set_cmap_entry(p,
+ hostx_set_cmap_entry(pScreen, p,
pdefs->red >> 8,
pdefs->green >> 8, pdefs->blue >> 8);
pdefs++;
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.h b/xorg-server/hw/kdrive/ephyr/ephyr.h
index 2395a7f7e..18bfe11ff 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr.h
+++ b/xorg-server/hw/kdrive/ephyr/ephyr.h
@@ -83,6 +83,7 @@ typedef struct _ephyrScrPriv {
KdScreenInfo *screen;
int mynum; /* Screen number */
+ unsigned long cmap[256];
/**
* Per-screen Xlib-using state for glamor (private to
diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c
index 8d6d5e83b..f64861b50 100644
--- a/xorg-server/hw/kdrive/ephyr/hostx.c
+++ b/xorg-server/hw/kdrive/ephyr/hostx.c
@@ -82,8 +82,6 @@ struct EphyrHostXVars {
KdScreenInfo **screens;
long damage_debug_msec;
-
- unsigned long cmap[256];
};
/* memset ( missing> ) instead of below */
@@ -751,9 +749,12 @@ hostx_calculate_color_shift(unsigned long mask)
}
void
-hostx_set_cmap_entry(unsigned char idx,
+hostx_set_cmap_entry(ScreenPtr pScreen, unsigned char idx,
unsigned char r, unsigned char g, unsigned char b)
{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
/* need to calculate the shifts for RGB because server could be BGR. */
/* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/
static int rshift, bshift, gshift = 0;
@@ -765,7 +766,7 @@ hostx_set_cmap_entry(unsigned char idx,
gshift = hostx_calculate_color_shift(HostX.visual->green_mask);
bshift = hostx_calculate_color_shift(HostX.visual->blue_mask);
}
- HostX.cmap[idx] = ((r << rshift) & HostX.visual->red_mask) |
+ scrpriv->cmap[idx] = ((r << rshift) & HostX.visual->red_mask) |
((g << gshift) & HostX.visual->green_mask) |
((b << bshift) & HostX.visual->blue_mask);
}
@@ -1017,7 +1018,7 @@ hostx_paint_rect(KdScreenInfo *screen,
unsigned char pixel =
*(unsigned char *) (scrpriv->fb_data + idx);
xcb_image_put_pixel(scrpriv->ximg, x, y,
- HostX.cmap[pixel]);
+ scrpriv->cmap[pixel]);
break;
}
default:
diff --git a/xorg-server/hw/kdrive/ephyr/hostx.h b/xorg-server/hw/kdrive/ephyr/hostx.h
index 87acd5a50..93aaa509c 100644
--- a/xorg-server/hw/kdrive/ephyr/hostx.h
+++ b/xorg-server/hw/kdrive/ephyr/hostx.h
@@ -141,7 +141,7 @@ hostx_get_visual_masks(KdScreenInfo *screen,
CARD32 *rmsk, CARD32 *gmsk, CARD32 *bmsk);
void
-hostx_set_cmap_entry(unsigned char idx,
+hostx_set_cmap_entry(ScreenPtr pScreen, unsigned char idx,
unsigned char r, unsigned char g, unsigned char b);
void *hostx_screen_init(KdScreenInfo *screen,
diff --git a/xorg-server/hw/xfree86/common/xf86AutoConfig.c b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
index 03dad150a..1450afbfc 100644
--- a/xorg-server/hw/xfree86/common/xf86AutoConfig.c
+++ b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
@@ -208,7 +208,6 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
if (xf86Info.consoleFd >= 0 && (i < (nmatches - 1))) {
struct vis_identifier visid;
const char *cp;
- extern char xf86SolarisFbDev[PATH_MAX];
int iret;
SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid));
diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c
index ffd66fad6..221ec530b 100644
--- a/xorg-server/hw/xfree86/dri2/dri2ext.c
+++ b/xorg-server/hw/xfree86/dri2/dri2ext.c
@@ -270,6 +270,9 @@ ProcDRI2GetBuffers(ClientPtr client)
unsigned int *attachments;
REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4);
+ if (stuff->count > (INT_MAX / 4))
+ return BadLength;
+
if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
&pDrawable, &status))
return status;
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am b/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am
index 5b08600c1..82c4f2f32 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am
+++ b/xorg-server/hw/xfree86/drivers/modesetting/Makefile.am
@@ -48,6 +48,9 @@ modesetting_drv_la_SOURCES = \
driver.h \
drmmode_display.c \
drmmode_display.h \
+ dumb_bo.c \
+ dumb_bo.h \
+ present.c \
vblank.c \
$(NULL)
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/dri2.c b/xorg-server/hw/xfree86/drivers/modesetting/dri2.c
index 6c88060b0..63cb0659d 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/dri2.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/dri2.c
@@ -43,8 +43,6 @@
#include "dri2.h"
#ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
enum ms_dri2_frame_event_type {
MS_DRI2_QUEUE_SWAP,
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/driver.c b/xorg-server/hw/xfree86/drivers/modesetting/driver.c
index 592f2469b..1ebf807e5 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/driver.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/driver.c
@@ -61,11 +61,6 @@
#include "driver.h"
-#ifdef GLAMOR
-#define GLAMOR_FOR_XORG 1
-#include "glamor.h"
-#endif
-
static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y);
static Bool CloseScreen(ScreenPtr pScreen);
static Bool EnterVT(ScrnInfoPtr pScrn);
@@ -453,11 +448,12 @@ dispatch_dirty_region(ScrnInfoPtr scrn,
modesettingPtr ms = modesettingPTR(scrn);
RegionPtr dirty = DamageRegion(damage);
unsigned num_cliprects = REGION_NUM_RECTS(dirty);
+ int ret = 0;
if (num_cliprects) {
drmModeClip *clip = malloc(num_cliprects * sizeof(drmModeClip));
BoxPtr rect = REGION_RECTS(dirty);
- int i, ret;
+ int i;
if (!clip)
return -ENOMEM;
@@ -474,12 +470,8 @@ dispatch_dirty_region(ScrnInfoPtr scrn,
ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
free(clip);
DamageEmpty(damage);
- if (ret) {
- if (ret == -EINVAL)
- return ret;
- }
}
- return 0;
+ return ret;
}
static void
@@ -593,7 +585,7 @@ try_enable_glamor(ScrnInfoPtr pScrn)
Bool do_glamor = (!accel_method_str ||
strcmp(accel_method_str, "glamor") == 0);
- ms->glamor = FALSE;
+ ms->drmmode.glamor = FALSE;
#ifdef GLAMOR
if (!do_glamor) {
@@ -604,7 +596,7 @@ try_enable_glamor(ScrnInfoPtr pScrn)
if (xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME)) {
if (glamor_egl_init(pScrn, ms->fd)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n");
- ms->glamor = TRUE;
+ ms->drmmode.glamor = TRUE;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"glamor initialization failed\n");
@@ -788,7 +780,7 @@ PreInit(ScrnInfoPtr pScrn, int flags)
try_enable_glamor(pScrn);
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
xf86LoadSubModule(pScrn, "dri2");
} else {
Bool prefer_shadow = TRUE;
@@ -861,7 +853,7 @@ msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
*size = stride;
- return ((uint8_t *) ms->drmmode.front_bo->ptr + row * stride + offset);
+ return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset);
}
static void
@@ -877,7 +869,8 @@ CreateScreenResources(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap;
Bool ret;
- void *pixels;
+ void *pixels = NULL;
+ int err;
pScreen->CreateScreenResources = ms->createScreenResources;
ret = pScreen->CreateScreenResources(pScreen);
@@ -886,27 +879,19 @@ CreateScreenResources(ScreenPtr pScreen)
if (!drmmode_set_desired_modes(pScrn, &ms->drmmode))
return FALSE;
-#ifdef GLAMOR
- if (ms->glamor) {
- if (!glamor_egl_create_textured_screen_ext(pScreen,
- ms->drmmode.front_bo->handle,
- pScrn->displayWidth *
- pScrn->bitsPerPixel / 8,
- NULL)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "glamor_egl_create_textured_screen_ext() failed\n");
- return FALSE;
- }
- }
-#endif
+ if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode))
+ return FALSE;
drmmode_uevent_init(pScrn, &ms->drmmode);
if (!ms->drmmode.sw_cursor)
drmmode_map_cursor_bos(pScrn, &ms->drmmode);
- pixels = drmmode_map_front_bo(&ms->drmmode);
- if (!pixels)
- return FALSE;
+
+ if (!ms->drmmode.gbm) {
+ pixels = drmmode_map_front_bo(&ms->drmmode);
+ if (!pixels)
+ return FALSE;
+ }
rootPixmap = pScreen->GetScreenPixmap(pScreen);
@@ -922,18 +907,22 @@ CreateScreenResources(ScreenPtr pScreen)
return FALSE;
}
- ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
- pScreen, rootPixmap);
+ err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0);
- if (ms->damage) {
- DamageRegister(&rootPixmap->drawable, ms->damage);
- ms->dirty_enabled = TRUE;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
- }
- else {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to create screen damage record\n");
- return FALSE;
+ if (err != -EINVAL && err != -ENOSYS) {
+ ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+ pScreen, rootPixmap);
+
+ if (ms->damage) {
+ DamageRegister(&rootPixmap->drawable, ms->damage);
+ ms->dirty_enabled = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to create screen damage record\n");
+ return FALSE;
+ }
}
return ret;
}
@@ -996,6 +985,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!SetMaster(pScrn))
return FALSE;
+#ifdef GLAMOR_HAS_GBM
+ if (ms->drmmode.glamor)
+ ms->drmmode.gbm = glamor_egl_get_gbm_device(pScreen);
+#endif
+
/* HW dependent - FIXME */
pScrn->displayWidth = pScrn->virtualX;
if (!drmmode_create_initial_bos(pScrn, &ms->drmmode))
@@ -1053,7 +1047,7 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
fbPictureInit(pScreen, NULL, 0);
#ifdef GLAMOR
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
if (!glamor_init(pScreen,
GLAMOR_USE_EGL_SCREEN |
GLAMOR_USE_SCREEN |
@@ -1106,6 +1100,19 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+#ifdef GLAMOR
+ if (ms->drmmode.glamor) {
+ XF86VideoAdaptorPtr glamor_adaptor;
+
+ glamor_adaptor = glamor_xv_init(pScreen, 16);
+ if (glamor_adaptor != NULL)
+ xf86XVScreenInit(pScreen, &glamor_adaptor, 1);
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to initialize XV support.\n");
+ }
+#endif
+
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@@ -1116,11 +1123,16 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
}
#ifdef GLAMOR
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
if (!ms_dri2_screen_init(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to initialize the DRI2 extension.\n");
}
+
+ if (!ms_present_screen_init(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to initialize the Present extension.\n");
+ }
}
#endif
@@ -1190,7 +1202,7 @@ CloseScreen(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
#ifdef GLAMOR
- if (ms->glamor) {
+ if (ms->drmmode.glamor) {
ms_dri2_close_screen(pScreen);
}
#endif
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/driver.h b/xorg-server/hw/xfree86/drivers/modesetting/driver.h
index 9eda1c4da..3decc3eea 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/driver.h
+++ b/xorg-server/hw/xfree86/drivers/modesetting/driver.h
@@ -33,6 +33,14 @@
#include <xf86Crtc.h>
#include <damage.h>
+#ifdef GLAMOR
+#define GLAMOR_FOR_XORG 1
+#include "glamor.h"
+#ifdef GLAMOR_HAS_GBM
+#include <gbm.h>
+#endif
+#endif
+
#include "drmmode_display.h"
#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
@@ -97,7 +105,6 @@ typedef struct _modesettingRec {
Bool dirty_enabled;
uint32_t cursor_width, cursor_height;
- Bool glamor;
} modesettingRec, *modesettingPtr;
#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
@@ -107,6 +114,10 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
ms_drm_handler_proc handler,
ms_drm_abort_proc abort);
+void ms_drm_abort(ScrnInfoPtr scrn,
+ Bool (*match)(void *data, void *match_data),
+ void *match_data);
+
xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
xf86CrtcPtr desired, BoxPtr crtc_box_ret);
@@ -122,3 +133,5 @@ void ms_dri2_close_screen(ScreenPtr screen);
Bool ms_vblank_screen_init(ScreenPtr screen);
void ms_vblank_close_screen(ScreenPtr screen);
+
+Bool ms_present_screen_init(ScreenPtr screen);
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c
index ef9009e98..824500bae 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -33,6 +33,7 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
+#include "dumb_bo.h"
#include "xf86str.h"
#include "X11/Xatom.h"
#include "micmap.h"
@@ -49,112 +50,64 @@
#include "driver.h"
-static struct dumb_bo *
-dumb_bo_create(int fd,
- const unsigned width, const unsigned height, const unsigned bpp)
-{
- struct drm_mode_create_dumb arg;
- struct dumb_bo *bo;
- int ret;
-
- bo = calloc(1, sizeof(*bo));
- if (!bo)
- return NULL;
-
- memset(&arg, 0, sizeof(arg));
- arg.width = width;
- arg.height = height;
- arg.bpp = bpp;
-
- ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
- if (ret)
- goto err_free;
-
- bo->handle = arg.handle;
- bo->size = arg.size;
- bo->pitch = arg.pitch;
-
- return bo;
- err_free:
- free(bo);
- return NULL;
-}
-
static int
-dumb_bo_map(int fd, struct dumb_bo *bo)
+drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
{
- struct drm_mode_map_dumb arg;
int ret;
- void *map;
- if (bo->ptr) {
- bo->map_count++;
- return 0;
+#ifdef GLAMOR_HAS_GBM
+ if (bo->gbm) {
+ gbm_bo_destroy(bo->gbm);
+ bo->gbm = NULL;
}
+#endif
- memset(&arg, 0, sizeof(arg));
- arg.handle = bo->handle;
-
- ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
- if (ret)
- return ret;
-
- map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, arg.offset);
- if (map == MAP_FAILED)
- return -errno;
+ if (bo->dumb) {
+ ret = dumb_bo_destroy(drmmode->fd, bo->dumb);
+ if (ret == 0)
+ bo->dumb = NULL;
+ }
- bo->ptr = map;
return 0;
}
-#if 0
-static int
-dumb_bo_unmap(int fd, struct dumb_bo *bo)
+static uint32_t
+drmmode_bo_get_pitch(drmmode_bo *bo)
{
- bo->map_count--;
- return 0;
-}
+#ifdef GLAMOR_HAS_GBM
+ if (bo->gbm)
+ return gbm_bo_get_stride(bo->gbm);
#endif
-int
-dumb_bo_destroy(int fd, struct dumb_bo *bo)
-{
- struct drm_mode_destroy_dumb arg;
- int ret;
-
- if (bo->ptr) {
- munmap(bo->ptr, bo->size);
- bo->ptr = NULL;
- }
-
- memset(&arg, 0, sizeof(arg));
- arg.handle = bo->handle;
- ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
- if (ret)
- return -errno;
-
- free(bo);
- return 0;
+ return bo->dumb->pitch;
}
-struct dumb_bo *
-dumb_get_bo_from_fd(int fd, int handle, int pitch, int size)
+uint32_t
+drmmode_bo_get_handle(drmmode_bo *bo)
{
- struct dumb_bo *bo;
- int ret;
+#ifdef GLAMOR_HAS_GBM
+ if (bo->gbm)
+ return gbm_bo_get_handle(bo->gbm).u32;
+#endif
- bo = calloc(1, sizeof(*bo));
- if (!bo)
- return NULL;
+ return bo->dumb->handle;
+}
- ret = drmPrimeFDToHandle(fd, handle, &bo->handle);
- if (ret) {
- free(bo);
- return NULL;
+static Bool
+drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
+ unsigned width, unsigned height, unsigned bpp)
+{
+#ifdef GLAMOR_HAS_GBM
+ if (drmmode->glamor) {
+ bo->gbm = gbm_bo_create(drmmode->gbm, width, height,
+ GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
+ return bo->gbm != NULL;
}
- bo->pitch = pitch;
- bo->size = size;
- return bo;
+#endif
+
+ bo->dumb = dumb_bo_create(drmmode->fd, width, height, bpp);
+ return bo->dumb != NULL;
}
Bool
@@ -232,18 +185,8 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
static void
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
-#if 0
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
-
-// drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-// drmmode_ptr drmmode = drmmode_crtc->drmmode;
-
- /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
- if (mode == DPMSModeOff) {
-// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
-// 0, 0, 0, NULL, 0, NULL);
- }
-#endif
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_crtc->dpms_mode = mode;
}
#if 0
@@ -315,8 +258,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
ret = drmModeAddFB(drmmode->fd,
pScrn->virtualX, height,
pScrn->depth, pScrn->bitsPerPixel,
- drmmode->front_bo->pitch,
- drmmode->front_bo->handle, &drmmode->fb_id);
+ drmmode_bo_get_pitch(&drmmode->front_bo),
+ drmmode_bo_get_handle(&drmmode->front_bo),
+ &drmmode->fb_id);
if (ret < 0) {
ErrorF("failed to add fb %d\n", ret);
return FALSE;
@@ -385,6 +329,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (crtc->scrn->pScreen)
xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+
+ crtc->funcs->dpms(crtc, DPMSModeOn);
+
/* go through all the outputs and force DPMS them back on? */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -432,25 +379,32 @@ drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
}
static void
-drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
+drmmode_set_cursor(xf86CrtcPtr crtc)
{
- modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- int i;
- uint32_t *ptr;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
uint32_t handle = drmmode_crtc->cursor_bo->handle;
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ static Bool use_set_cursor2 = TRUE;
int ret;
- /* cursor should be mapped already */
- ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
+ if (use_set_cursor2) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ CursorPtr cursor = xf86_config->cursor;
- for (i = 0; i < ms->cursor_width * ms->cursor_height; i++)
- ptr[i] = image[i]; // cpu_to_le32(image[i]);
+ ret =
+ drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ handle, ms->cursor_width, ms->cursor_height,
+ cursor->bits->xhot, cursor->bits->yhot);
+ if (ret == -EINVAL)
+ use_set_cursor2 = FALSE;
+ else
+ return;
+ }
+
+ ret = drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
+ ms->cursor_width, ms->cursor_height);
- ret =
- drmModeSetCursor(drmmode_crtc->drmmode->fd,
- drmmode_crtc->mode_crtc->crtc_id, handle,
- ms->cursor_width, ms->cursor_height);
if (ret) {
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
@@ -462,46 +416,44 @@ drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
}
static void
-drmmode_hide_cursor(xf86CrtcPtr crtc)
+drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int i;
+ uint32_t *ptr;
- drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
- ms->cursor_width, ms->cursor_height);
+ /* cursor should be mapped already */
+ ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
+
+ for (i = 0; i < ms->cursor_width * ms->cursor_height; i++)
+ ptr[i] = image[i]; // cpu_to_le32(image[i]);
+ if (drmmode_crtc->cursor_up)
+ drmmode_set_cursor(crtc);
}
static void
-drmmode_show_cursor(xf86CrtcPtr crtc)
+drmmode_hide_cursor(xf86CrtcPtr crtc)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- uint32_t handle = drmmode_crtc->cursor_bo->handle;
- static Bool use_set_cursor2 = TRUE;
-
- if (use_set_cursor2) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
- CursorPtr cursor = xf86_config->cursor;
- int ret;
-
- ret =
- drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- handle, ms->cursor_width, ms->cursor_height,
- cursor->bits->xhot, cursor->bits->yhot);
- if (ret == -EINVAL)
- use_set_cursor2 = FALSE;
- else
- return;
- }
- drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
+ drmmode_crtc->cursor_up = FALSE;
+ drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
ms->cursor_width, ms->cursor_height);
}
static void
+drmmode_show_cursor(xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_crtc->cursor_up = TRUE;
+ drmmode_set_cursor(crtc);
+}
+
+static void
drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
uint16_t * blue, int size)
{
@@ -1019,8 +971,7 @@ static const char *const output_names[] = {
};
static void
-drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num,
- int *num_dvi, int *num_hdmi)
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
{
xf86OutputPtr output;
drmModeConnectorPtr koutput;
@@ -1172,6 +1123,42 @@ drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
}
}
+Bool
+drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode)
+{
+#ifdef GLAMOR
+ ScrnInfoPtr scrn = drmmode->scrn;
+ ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn);
+ PixmapPtr screen_pixmap;
+ void *gbm_bo;
+
+ if (!drmmode->glamor)
+ return TRUE;
+
+#ifdef GLAMOR_HAS_GBM
+ gbm_bo = drmmode->front_bo.gbm;
+ screen_pixmap = screen->GetScreenPixmap(screen);
+
+ if (!glamor_egl_create_textured_pixmap_from_gbm_bo(screen_pixmap, gbm_bo)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed");
+ return FALSE;
+ }
+ glamor_set_screen_pixmap(screen_pixmap, NULL);
+#else
+ if (!glamor_egl_create_textured_screen(screen,
+ drmmode_bo_get_handle(&drmmode->front_bo),
+ scrn->displayWidth *
+ scrn->bitsPerPixel / 8)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "glamor_egl_create_textured_screen() failed\n");
+ return FALSE;
+ }
+#endif
+#endif
+
+ return TRUE;
+}
+
static Bool
drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
{
@@ -1180,14 +1167,14 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
drmmode_crtc_private_ptr
drmmode_crtc = xf86_config->crtc[0]->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- struct dumb_bo *old_front = NULL;
+ drmmode_bo old_front;
Bool ret;
ScreenPtr screen = xf86ScrnToScreen(scrn);
uint32_t old_fb_id;
int i, pitch, old_width, old_height, old_pitch;
int cpp = (scrn->bitsPerPixel + 7) / 8;
PixmapPtr ppix = screen->GetScreenPixmap(screen);
- void *new_pixels;
+ void *new_pixels = NULL;
if (scrn->virtualX == width && scrn->virtualY == height)
return TRUE;
@@ -1202,16 +1189,15 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
old_width = scrn->virtualX;
old_height = scrn->virtualY;
- old_pitch = drmmode->front_bo->pitch;
+ old_pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
old_fb_id = drmmode->fb_id;
old_front = drmmode->front_bo;
- drmmode->front_bo =
- dumb_bo_create(drmmode->fd, width, height, scrn->bitsPerPixel);
- if (!drmmode->front_bo)
+ if (!drmmode_create_bo(drmmode, &drmmode->front_bo,
+ width, height, scrn->bitsPerPixel))
goto fail;
- pitch = drmmode->front_bo->pitch;
+ pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
scrn->virtualX = width;
scrn->virtualY = height;
@@ -1219,30 +1205,32 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
scrn->bitsPerPixel, pitch,
- drmmode->front_bo->handle, &drmmode->fb_id);
+ drmmode_bo_get_handle(&drmmode->front_bo),
+ &drmmode->fb_id);
if (ret)
goto fail;
- new_pixels = drmmode_map_front_bo(drmmode);
- if (!new_pixels)
- goto fail;
+ if (!drmmode->gbm) {
+ new_pixels = drmmode_map_front_bo(drmmode);
+ if (!new_pixels)
+ goto fail;
+ }
- if (!drmmode->shadow_enable)
- screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
- pitch, new_pixels);
- else {
- void *new_shadow;
+ if (drmmode->shadow_enable) {
uint32_t size = scrn->displayWidth * scrn->virtualY *
((scrn->bitsPerPixel + 7) >> 3);
- new_shadow = calloc(1, size);
- if (new_shadow == NULL)
+ new_pixels = calloc(1, size);
+ if (new_pixels == NULL)
goto fail;
free(drmmode->shadow_fb);
- drmmode->shadow_fb = new_shadow;
- screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
- pitch, drmmode->shadow_fb);
+ drmmode->shadow_fb = new_pixels;
}
+ screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, new_pixels);
+
+ if (!drmmode_glamor_handle_new_screen_pixmap(drmmode))
+ goto fail;
+
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -1255,14 +1243,13 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
if (old_fb_id) {
drmModeRmFB(drmmode->fd, old_fb_id);
- dumb_bo_destroy(drmmode->fd, old_front);
+ drmmode_bo_destroy(drmmode, &old_front);
}
return TRUE;
fail:
- if (drmmode->front_bo)
- dumb_bo_destroy(drmmode->fd, drmmode->front_bo);
+ drmmode_bo_destroy(drmmode, &drmmode->front_bo);
drmmode->front_bo = old_front;
scrn->virtualX = old_width;
scrn->virtualY = old_height;
@@ -1279,7 +1266,7 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
Bool
drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
{
- int i, num_dvi = 0, num_hdmi = 0;
+ int i;
int ret;
uint64_t value = 0;
@@ -1307,7 +1294,7 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
drmmode_crtc_init(pScrn, drmmode, i);
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
- drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
+ drmmode_output_init(pScrn, drmmode, i);
/* workout clones */
drmmode_clones_init(pScrn, drmmode);
@@ -1468,7 +1455,7 @@ drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
return TRUE;
}
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
static void
drmmode_handle_uevents(int fd, void *closure)
{
@@ -1488,7 +1475,7 @@ drmmode_handle_uevents(int fd, void *closure)
void
drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
{
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
struct udev *u;
struct udev_monitor *mon;
@@ -1521,7 +1508,7 @@ drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
void
drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
{
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
if (drmmode->uevent_handler) {
struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
@@ -1548,10 +1535,9 @@ drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
width = pScrn->virtualX;
height = pScrn->virtualY;
- drmmode->front_bo = dumb_bo_create(drmmode->fd, width, height, bpp);
- if (!drmmode->front_bo)
+ if (!drmmode_create_bo(drmmode, &drmmode->front_bo, width, height, bpp))
return FALSE;
- pScrn->displayWidth = drmmode->front_bo->pitch / cpp;
+ pScrn->displayWidth = drmmode_bo_get_pitch(&drmmode->front_bo) / cpp;
width = ms->cursor_width;
height = ms->cursor_height;
@@ -1571,14 +1557,14 @@ drmmode_map_front_bo(drmmode_ptr drmmode)
{
int ret;
- if (drmmode->front_bo->ptr)
- return drmmode->front_bo->ptr;
+ if (drmmode->front_bo.dumb->ptr)
+ return drmmode->front_bo.dumb->ptr;
- ret = dumb_bo_map(drmmode->fd, drmmode->front_bo);
+ ret = dumb_bo_map(drmmode->fd, drmmode->front_bo.dumb);
if (ret)
return NULL;
- return drmmode->front_bo->ptr;
+ return drmmode->front_bo.dumb->ptr;
}
@@ -1625,8 +1611,7 @@ drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
drmmode->fb_id = 0;
}
- dumb_bo_destroy(drmmode->fd, drmmode->front_bo);
- drmmode->front_bo = NULL;
+ drmmode_bo_destroy(drmmode, &drmmode->front_bo);
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h
index 987608c55..66d0ca260 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/xorg-server/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -28,17 +28,20 @@
#define DRMMODE_DISPLAY_H
#include "xf86drmMode.h"
-#ifdef HAVE_UDEV
+#ifdef CONFIG_UDEV_KMS
#include "libudev.h"
#endif
-struct dumb_bo {
- uint32_t handle;
- uint32_t size;
- void *ptr;
- int map_count;
- uint32_t pitch;
-};
+#include "dumb_bo.h"
+
+struct gbm_device;
+
+typedef struct {
+ struct dumb_bo *dumb;
+#ifdef GLAMOR_HAS_GBM
+ struct gbm_bo *gbm;
+#endif
+} drmmode_bo;
typedef struct {
int fd;
@@ -48,14 +51,18 @@ typedef struct {
drmModeFBPtr mode_fb;
int cpp;
ScrnInfoPtr scrn;
-#ifdef HAVE_UDEV
+
+ struct gbm_device *gbm;
+
+#ifdef CONFIG_UDEV_KMS
struct udev_monitor *uevent_monitor;
InputHandlerProc uevent_handler;
#endif
drmEventContext event_context;
- struct dumb_bo *front_bo;
+ drmmode_bo front_bo;
Bool sw_cursor;
+ Bool glamor;
Bool shadow_enable;
void *shadow_fb;
@@ -79,7 +86,9 @@ typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
uint32_t vblank_pipe;
+ int dpms_mode;
struct dumb_bo *cursor_bo;
+ Bool cursor_up;
unsigned rotate_fb_id;
uint16_t lut_r[256], lut_g[256], lut_b[256];
DamagePtr slave_damage;
@@ -128,6 +137,8 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec;
#define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec))
+uint32_t drmmode_bo_get_handle(drmmode_bo *bo);
+Bool drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode);
void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv);
Bool drmmode_SetSlaveBO(PixmapPtr ppix,
drmmode_ptr drmmode,
@@ -147,8 +158,6 @@ Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
void drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode,
int *depth, int *bpp);
-struct dumb_bo *dumb_get_bo_from_fd(int drm_fd, int fd, int pitch, int size);
-int dumb_bo_destroy(int fd, struct dumb_bo *bo);
#ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c
new file mode 100644
index 000000000..58d420e07
--- /dev/null
+++ b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#include "dumb_bo.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <xf86drm.h>
+
+struct dumb_bo *
+dumb_bo_create(int fd,
+ const unsigned width, const unsigned height, const unsigned bpp)
+{
+ struct drm_mode_create_dumb arg;
+ struct dumb_bo *bo;
+ int ret;
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo)
+ return NULL;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.width = width;
+ arg.height = height;
+ arg.bpp = bpp;
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
+ if (ret)
+ goto err_free;
+
+ bo->handle = arg.handle;
+ bo->size = arg.size;
+ bo->pitch = arg.pitch;
+
+ return bo;
+ err_free:
+ free(bo);
+ return NULL;
+}
+
+int
+dumb_bo_map(int fd, struct dumb_bo *bo)
+{
+ struct drm_mode_map_dumb arg;
+ int ret;
+ void *map;
+
+ if (bo->ptr) {
+ return 0;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->handle;
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
+ if (ret)
+ return ret;
+
+ map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, arg.offset);
+ if (map == MAP_FAILED)
+ return -errno;
+
+ bo->ptr = map;
+ return 0;
+}
+
+int
+dumb_bo_destroy(int fd, struct dumb_bo *bo)
+{
+ struct drm_mode_destroy_dumb arg;
+ int ret;
+
+ if (bo->ptr) {
+ munmap(bo->ptr, bo->size);
+ bo->ptr = NULL;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->handle;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
+ if (ret)
+ return -errno;
+
+ free(bo);
+ return 0;
+}
+
+struct dumb_bo *
+dumb_get_bo_from_fd(int fd, int handle, int pitch, int size)
+{
+ struct dumb_bo *bo;
+ int ret;
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo)
+ return NULL;
+
+ ret = drmPrimeFDToHandle(fd, handle, &bo->handle);
+ if (ret) {
+ free(bo);
+ return NULL;
+ }
+ bo->pitch = pitch;
+ bo->size = size;
+ return bo;
+}
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h
new file mode 100644
index 000000000..9235e61e2
--- /dev/null
+++ b/xorg-server/hw/xfree86/drivers/modesetting/dumb_bo.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+#ifndef DUMB_BO_H
+#define DUMB_BO_H
+
+#include <stdint.h>
+
+struct dumb_bo {
+ uint32_t handle;
+ uint32_t size;
+ void *ptr;
+ uint32_t pitch;
+};
+
+struct dumb_bo *dumb_bo_create(int fd, const unsigned width,
+ const unsigned height, const unsigned bpp);
+int dumb_bo_map(int fd, struct dumb_bo *bo);
+int dumb_bo_destroy(int fd, struct dumb_bo *bo);
+struct dumb_bo *dumb_get_bo_from_fd(int fd, int handle, int pitch, int size);
+
+#endif
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/present.c b/xorg-server/hw/xfree86/drivers/modesetting/present.c
new file mode 100644
index 000000000..359e11316
--- /dev/null
+++ b/xorg-server/hw/xfree86/drivers/modesetting/present.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <xf86.h>
+#include <xf86Crtc.h>
+#include <xf86drm.h>
+#include <xf86str.h>
+#include <present.h>
+
+#include "driver.h"
+
+#if 0
+#define DebugPresent(x) ErrorF x
+#else
+#define DebugPresent(x)
+#endif
+
+struct ms_present_vblank_event {
+ uint64_t event_id;
+};
+
+static RRCrtcPtr
+ms_present_get_crtc(WindowPtr window)
+{
+ xf86CrtcPtr xf86_crtc = ms_dri2_crtc_covering_drawable(&window->drawable);
+ return xf86_crtc ? xf86_crtc->randr_crtc : NULL;
+}
+
+static int
+ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+
+ return ms_get_crtc_ust_msc(xf86_crtc, ust, msc);
+}
+
+/*
+ * Flush the DRM event queue when full; makes space for new events.
+ */
+static Bool
+ms_flush_drm_events(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+
+ struct pollfd p = { .fd = ms->fd, .events = POLLIN };
+ int r;
+
+ do {
+ r = poll(&p, 1, 0);
+ } while (r == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (r <= 0)
+ return TRUE;
+
+ return drmHandleEvent(ms->fd, &ms->event_context) >= 0;
+}
+
+/*
+ * Called when the queued vblank event has occurred
+ */
+static void
+ms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data)
+{
+ struct ms_present_vblank_event *event = data;
+
+ DebugPresent(("\t\tmh %lld msc %llu\n",
+ (long long) event->event_id, (long long) msc));
+
+ present_event_notify(event->event_id, usec, msc);
+ free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+ms_present_vblank_abort(void *data)
+{
+ struct ms_present_vblank_event *event = data;
+
+ DebugPresent(("\t\tma %lld\n", (long long) event->event_id));
+
+ free(event);
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+ms_present_queue_vblank(RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ struct ms_present_vblank_event *event;
+ drmVBlank vbl;
+ int ret;
+ uint32_t seq;
+
+ event = calloc(sizeof(struct ms_present_vblank_event), 1);
+ if (!event)
+ return BadAlloc;
+ event->event_id = event_id;
+ seq = ms_drm_queue_alloc(xf86_crtc, event,
+ ms_present_vblank_handler,
+ ms_present_vblank_abort);
+ if (!seq) {
+ free(event);
+ return BadAlloc;
+ }
+
+ vbl.request.type =
+ DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
+ vbl.request.sequence = ms_crtc_msc_to_kernel_msc(xf86_crtc, msc);
+ vbl.request.signal = seq;
+ for (;;) {
+ ret = drmWaitVBlank(ms->fd, &vbl);
+ if (!ret)
+ break;
+ if (errno != EBUSY || !ms_flush_drm_events(screen))
+ return BadAlloc;
+ }
+ DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n",
+ (long long) event_id, seq, (long long) msc,
+ vbl.request.sequence));
+ return Success;
+}
+
+static Bool
+ms_present_event_match(void *data, void *match_data)
+{
+ struct ms_present_vblank_event *event = data;
+ uint64_t *match = match_data;
+
+ return *match == event->event_id;
+}
+
+/*
+ * Remove a pending vblank event from the DRM queue so that it is not reported
+ * to the extension
+ */
+static void
+ms_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ ms_drm_abort(scrn, ms_present_event_match, &event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+ms_present_flush(WindowPtr window)
+{
+#ifdef GLAMOR
+ ScreenPtr screen = window->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+
+ if (ms->drmmode.glamor)
+ glamor_block_handler(screen);
+#endif
+}
+
+static present_screen_info_rec ms_present_screen_info = {
+ .version = PRESENT_SCREEN_INFO_VERSION,
+
+ .get_crtc = ms_present_get_crtc,
+ .get_ust_msc = ms_present_get_ust_msc,
+ .queue_vblank = ms_present_queue_vblank,
+ .abort_vblank = ms_present_abort_vblank,
+ .flush = ms_present_flush,
+
+ .capabilities = PresentCapabilityNone,
+ .check_flip = 0,
+ .flip = 0,
+ .unflip = 0,
+};
+
+Bool
+ms_present_screen_init(ScreenPtr screen)
+{
+ return present_screen_init(screen, &ms_present_screen_info);
+}
diff --git a/xorg-server/hw/xfree86/drivers/modesetting/vblank.c b/xorg-server/hw/xfree86/drivers/modesetting/vblank.c
index 5031ef8ff..711f6edb3 100644
--- a/xorg-server/hw/xfree86/drivers/modesetting/vblank.c
+++ b/xorg-server/hw/xfree86/drivers/modesetting/vblank.c
@@ -88,6 +88,14 @@ static int ms_box_area(BoxPtr box)
return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
}
+static Bool
+ms_crtc_on(xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
+}
+
/*
* Return the crtc covering 'box'. If two crtcs cover a portion of
* 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
@@ -114,7 +122,7 @@ ms_covering_crtc(ScrnInfoPtr scrn,
crtc = xf86_config->crtc[c];
/* If the CRTC is off, treat it as not covering */
- if (!crtc->enabled)
+ if (!ms_crtc_on(crtc))
continue;
ms_crtc_box(crtc, &crtc_box);
@@ -323,6 +331,24 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn)
}
/*
+ * Externally usable abort function that uses a callback to match a single
+ * queued entry to abort
+ */
+void
+ms_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data),
+ void *match_data)
+{
+ struct ms_drm_queue *q;
+
+ xorg_list_for_each_entry(q, &ms_drm_queue, list) {
+ if (match(q->data, match_data)) {
+ ms_drm_abort_one(q);
+ break;
+ }
+ }
+}
+
+/*
* General DRM kernel handler. Looks for the matching sequence number in the
* drm event queue and calls the handler for it.
*/
diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
index 16fc1b739..cc50f36c4 100644
--- a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
+++ b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
@@ -46,15 +46,12 @@
#define SOL_CONSOLE_DEV "/dev/console"
static Bool KeepTty = FALSE;
-static Bool Protect0 = FALSE;
static Bool UseConsole = FALSE;
#ifdef HAS_USL_VTS
static int VTnum = -1;
static int xf86StartVT = -1;
static int vtEnabled = 0;
-extern void xf86VTAcquire(int);
-extern void xf86VTRelease(int);
#endif
/* Device to open as xf86Info.consoleFd */
@@ -97,27 +94,6 @@ xf86OpenConsole(void)
if (geteuid() != 0)
FatalError("xf86OpenConsole: Server must be suid root\n");
- /* Protect page 0 to help find NULL dereferencing */
- /* mprotect() doesn't seem to work */
- if (Protect0) {
- int fd = -1;
-
- if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0) {
- xf86Msg(X_WARNING,
- "xf86OpenConsole: cannot open /dev/zero (%s)\n",
- strerror(errno));
- }
- else {
- if (mmap(0, 0x1000, PROT_NONE,
- MAP_FIXED | MAP_SHARED, fd, 0) == MAP_FAILED)
- xf86Msg(X_WARNING,
- "xf86OpenConsole: failed to protect page 0 (%s)\n",
- strerror(errno));
-
- close(fd);
- }
- }
-
#ifdef HAS_USL_VTS
/*
@@ -371,15 +347,6 @@ xf86ProcessArgument(int argc, char **argv, int i)
}
/*
- * Undocumented flag to protect page 0 from read/write to help catch NULL
- * pointer dereferences. This is purely a debugging flag.
- */
- if (!strcmp(argv[i], "-protect0")) {
- Protect0 = TRUE;
- return 1;
- }
-
- /*
* Use /dev/console as the console device.
*/
if (!strcmp(argv[i], "-C")) {
diff --git a/xorg-server/hw/xfree86/os-support/xf86_OSlib.h b/xorg-server/hw/xfree86/os-support/xf86_OSlib.h
index 3a83f348f..6190fe6a0 100644
--- a/xorg-server/hw/xfree86/os-support/xf86_OSlib.h
+++ b/xorg-server/hw/xfree86/os-support/xf86_OSlib.h
@@ -134,10 +134,15 @@
#endif
#include <sys/kd.h>
#include <sys/vt.h>
+
+extern _X_HIDDEN void xf86VTAcquire(int);
+extern _X_HIDDEN void xf86VTRelease(int);
#endif
#if defined(sun)
#include <sys/fbio.h>
+extern _X_HIDDEN char xf86SolarisFbDev[PATH_MAX];
+
#include <sys/kbd.h>
#include <sys/kbio.h>
diff --git a/xorg-server/hw/xwayland/xwayland-glamor.c b/xorg-server/hw/xwayland/xwayland-glamor.c
index 4be883fa3..09b454f8a 100644
--- a/xorg-server/hw/xwayland/xwayland-glamor.c
+++ b/xorg-server/hw/xwayland/xwayland-glamor.c
@@ -398,9 +398,8 @@ xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
}
void
-glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap)
+glamor_egl_destroy_pixmap_image(PixmapPtr pixmap)
{
- glamor_destroy_textured_pixmap(pixmap);
}
int
diff --git a/xorg-server/hw/xwayland/xwayland-input.c b/xorg-server/hw/xwayland/xwayland-input.c
index b8c543ce4..5e204189f 100644
--- a/xorg-server/hw/xwayland/xwayland-input.c
+++ b/xorg-server/hw/xwayland/xwayland-input.c
@@ -233,6 +233,9 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
xwl_seat->xwl_screen->serial = serial;
switch (button) {
+ case BTN_LEFT:
+ index = 1;
+ break;
case BTN_MIDDLE:
index = 2;
break;
@@ -240,7 +243,9 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
index = 3;
break;
default:
- index = button - BTN_LEFT + 1;
+ /* Skip indexes 4-7: they are used for vertical and horizontal scroll.
+ The rest of the buttons go in order: BTN_SIDE becomes 8, etc. */
+ index = 8 + button - BTN_SIDE;
break;
}
diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c
index fef46a94f..654c58c14 100644
--- a/xorg-server/hw/xwin/InitOutput.c
+++ b/xorg-server/hw/xwin/InitOutput.c
@@ -793,6 +793,10 @@ winUseMsg(void)
#ifdef XWIN_CLIPBOARD
ErrorF("-nounicodeclipboard\n"
"\tDo not use Unicode clipboard even if on a NT-based platform.\n");
+
+ ErrorF("-[no]primary\n"
+ "\tWhen clipboard integration is enabled, map the X11 PRIMARY selection\n"
+ "\tto the Windows clipboard. Default is enabled.\n");
#endif
ErrorF("-refresh rate_in_Hz\n"
diff --git a/xorg-server/hw/xwin/XWin.rc b/xorg-server/hw/xwin/XWin.rc
index a142f3070..a54e0fdbb 100644
--- a/xorg-server/hw/xwin/XWin.rc
+++ b/xorg-server/hw/xwin/XWin.rc
@@ -93,6 +93,7 @@ BEGIN
POPUP "TRAYICON_MENU"
BEGIN
MENUITEM "&Hide Root Window", ID_APP_HIDE_ROOT
+ MENUITEM "Clipboard may use &PRIMARY selection", ID_APP_MONITOR_PRIMARY
MENUITEM "&About...", ID_APP_ABOUT
MENUITEM SEPARATOR
MENUITEM "E&xit...", ID_APP_EXIT
diff --git a/xorg-server/hw/xwin/man/XWin.man b/xorg-server/hw/xwin/man/XWin.man
index a043ac281..15a57db02 100644
--- a/xorg-server/hw/xwin/man/XWin.man
+++ b/xorg-server/hw/xwin/man/XWin.man
@@ -174,7 +174,7 @@ on remote hosts, when that information is available and it's useful to do so.
.SH OPTIONS CONTROLLING WINDOWS INTEGRATION
.TP 8
.B \-[no]clipboard
-Enables [disables] the integration between the Cygwin/X clipboard and
+Enables [disables] the integration between the X11 clipboard and
\fIWindows\fP clipboard. The default is enabled.
.TP 8
.B "\-emulate3buttons [\fItimeout\fP]"
@@ -200,6 +200,10 @@ prevents the \fIWindows\fP mouse cursor from being drawn on top of the X
cursor.
This parameter has no effect unless \fB-swcursor\fP is also specified.
.TP 8
+.B \-[no]primary
+Clipboard integration may [will not] use the PRIMARY selection.
+The default is enabled.
+.TP 8
.B \-swcursor
Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead.
.TP 8
diff --git a/xorg-server/hw/xwin/winclipboard/internal.h b/xorg-server/hw/xwin/winclipboard/internal.h
index 94956f80d..c6bde84af 100644
--- a/xorg-server/hw/xwin/winclipboard/internal.h
+++ b/xorg-server/hw/xwin/winclipboard/internal.h
@@ -39,10 +39,12 @@
#include <X11/Xwindows.h>
#define WIN_XEVENTS_SUCCESS 0
-#define WIN_XEVENTS_CONVERT 2
-#define WIN_XEVENTS_NOTIFY 3
+#define WIN_XEVENTS_FAILED 1
+#define WIN_XEVENTS_NOTIFY_DATA 3
+#define WIN_XEVENTS_NOTIFY_TARGETS 4
#define WM_WM_REINIT (WM_USER + 1)
+#define WM_WM_QUIT (WM_USER + 2)
/*
* References to external symbols
@@ -95,9 +97,15 @@ typedef struct
* winclipboardxevents.c
*/
+typedef struct
+{
+ Bool fUseUnicode;
+ Atom *targetList;
+} ClipboardConversionData;
+
int
winClipboardFlushXEvents(HWND hwnd,
- Window iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom);
+ Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atom);
Atom
diff --git a/xorg-server/hw/xwin/winclipboard/thread.c b/xorg-server/hw/xwin/winclipboard/thread.c
index c179e3f83..50e1e8cb5 100644
--- a/xorg-server/hw/xwin/winclipboard/thread.c
+++ b/xorg-server/hw/xwin/winclipboard/thread.c
@@ -123,6 +123,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
int iSelectError;
Bool fShutdown = FALSE;
static Bool fErrorHandlerSet = FALSE;
+ ClipboardConversionData data;
winDebug("winClipboardProc - Hello\n");
@@ -254,21 +255,25 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
}
}
- /* Pre-flush X events */
- /*
- * NOTE: Apparently you'll freeze if you don't do this,
- * because there may be events in local data structures
- * already.
- */
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
-
- /* Pre-flush Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
- ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
- }
+ data.fUseUnicode = fUseUnicode;
- /* Loop for X events */
+ /* Loop for events */
while (1) {
+
+ /* Process X events */
+ winClipboardFlushXEvents(hwnd,
+ iWindow, pDisplay, &data, &atoms);
+
+ /* Process Windows messages */
+ if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+ ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue trapped "
+ "WM_QUIT message, exiting main loop.\n");
+ break;
+ }
+
+ /* We need to ensure that all pending requests are sent */
+ XFlush(pDisplay);
+
/* Setup the file descriptor set */
/*
* NOTE: You have to do this before every call to select
@@ -315,10 +320,9 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
break;
}
- /* Branch on which descriptor became active */
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
- /* Process X events */
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
+ winDebug
+ ("winClipboardProc - X connection ready, pumping X event queue\n");
}
#ifdef HAS_DEVWINDOWS
@@ -328,14 +332,16 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
if (1)
#endif
{
- /* Process Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
- ErrorF("winClipboardProc - "
- "winClipboardFlushWindowsMessageQueue trapped "
- "WM_QUIT message, exiting main loop.\n");
- break;
- }
+ winDebug
+ ("winClipboardProc - /dev/windows ready, pumping Windows message queue\n");
}
+
+#ifdef HAS_DEVWINDOWS
+ if (!(FD_ISSET(iConnectionNumber, &fdsRead)) &&
+ !(FD_ISSET(fdMessageQueue, &fdsRead))) {
+ winDebug("winClipboardProc - Spurious wake, select() returned %d\n", iReturn);
+ }
+#endif
}
winClipboardProc_Exit:
@@ -345,7 +351,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
winClipboardProc_Done:
/* Close our Windows window */
if (g_hwndClipboard) {
- winClipboardWindowDestroy();
+ DestroyWindow(g_hwndClipboard);
}
/* Close our X window */
@@ -485,7 +491,7 @@ void
winClipboardWindowDestroy(void)
{
if (g_hwndClipboard) {
- SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
+ SendMessage(g_hwndClipboard, WM_WM_QUIT, 0, 0);
}
}
diff --git a/xorg-server/hw/xwin/winclipboard/winclipboard.h b/xorg-server/hw/xwin/winclipboard/winclipboard.h
index 52481301b..9c5c568a7 100644
--- a/xorg-server/hw/xwin/winclipboard/winclipboard.h
+++ b/xorg-server/hw/xwin/winclipboard/winclipboard.h
@@ -33,4 +33,6 @@ void winFixClipboardChain(void);
void winClipboardWindowDestroy(void);
+extern Bool fPrimarySelection;
+
#endif
diff --git a/xorg-server/hw/xwin/winclipboard/wndproc.c b/xorg-server/hw/xwin/winclipboard/wndproc.c
index 165ff558a..1ea5bc6b7 100644
--- a/xorg-server/hw/xwin/winclipboard/wndproc.c
+++ b/xorg-server/hw/xwin/winclipboard/wndproc.c
@@ -45,6 +45,7 @@
#include <sys/types.h>
#include <sys/time.h>
+#include <limits.h>
#include <X11/Xatom.h>
@@ -64,7 +65,7 @@
static int
winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
- Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec)
+ ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec)
{
int iConnNumber;
struct timeval tv;
@@ -82,8 +83,18 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
fd_set fdsRead;
long remainingTime;
- /* We need to ensure that all pending events are processed */
- XSync(pDisplay, FALSE);
+ /* Process X events */
+ iReturn = winClipboardFlushXEvents(hwnd, iWindow, pDisplay, data, atoms);
+
+ winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn);
+
+ if ((WIN_XEVENTS_NOTIFY_DATA == iReturn) || (WIN_XEVENTS_NOTIFY_TARGETS == iReturn) || (WIN_XEVENTS_FAILED == iReturn)) {
+ /* Bail out */
+ return iReturn;
+ }
+
+ /* We need to ensure that all pending requests are sent */
+ XFlush(pDisplay);
/* Setup the file descriptor set */
FD_ZERO(&fdsRead);
@@ -112,24 +123,8 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
break;
}
- /* Branch on which descriptor became active */
- if (FD_ISSET(iConnNumber, &fdsRead)) {
- /* Process X events */
- /* Exit when we see that server is shutting down */
- iReturn = winClipboardFlushXEvents(hwnd,
- iWindow, pDisplay, fUseUnicode, atoms);
-
- winDebug
- ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
- iReturn);
-
- if (WIN_XEVENTS_NOTIFY == iReturn) {
- /* Bail out if notify processed */
- return iReturn;
- }
- }
- else {
- winDebug("winProcessXEventsTimeout - Spurious wake\n");
+ if (!FD_ISSET(iConnNumber, &fdsRead)) {
+ winDebug("winProcessXEventsTimeout - Spurious wake, select() returned %d\n", iReturn);
}
}
@@ -148,6 +143,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static Display *pDisplay;
static Window iWindow;
static ClipboardAtoms *atoms;
+ static Bool fRunning;
/* Branch on message type */
switch (message) {
@@ -159,7 +155,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
ChangeClipboardChain(hwnd, s_hwndNextViewer);
s_hwndNextViewer = NULL;
+ }
+ return 0;
+ case WM_WM_QUIT:
+ {
+ winDebug("winClipboardWindowProc - WM_WM_QUIT\n");
+ fRunning = FALSE;
PostQuitMessage(0);
}
return 0;
@@ -175,6 +177,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
pDisplay = cwcp->pClipboardDisplay;
iWindow = cwcp->iClipboardWindow;
atoms = cwcp->atoms;
+ fRunning = TRUE;
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
if (first == hwnd)
@@ -307,6 +310,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
+ /* Bail when shutting down */
+ if (!fRunning)
+ return 0;
+
/*
* Do not take ownership of the X11 selections when something
* other than CF_TEXT or CF_UNICODETEXT has been copied
@@ -410,93 +417,151 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
return 0;
- case WM_RENDERFORMAT:
case WM_RENDERALLFORMATS:
+ winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n");
+
+ /*
+ WM_RENDERALLFORMATS is sent as we are shutting down, to render the
+ clipboard so it's contents remains available to other applications.
+
+ Unfortunately, this can't work without major changes. The server is
+ already waiting for us to stop, so we can't ask for the rendering of
+ clipboard text now.
+ */
+
+ return 0;
+
+ case WM_RENDERFORMAT:
{
int iReturn;
Bool fConvertToUnicode;
+ Bool pasted = FALSE;
+ Atom selection;
+ ClipboardConversionData data;
+ int best_target = 0;
- winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
+ winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n",
+ wParam);
/* Flag whether to convert to Unicode or not */
- if (message == WM_RENDERALLFORMATS)
- fConvertToUnicode = FALSE;
- else
- fConvertToUnicode = (CF_UNICODETEXT == wParam);
+ fConvertToUnicode = (CF_UNICODETEXT == wParam);
- /* Request the selection contents */
- iReturn = XConvertSelection(pDisplay,
- winClipboardGetLastOwnedSelectionAtom(atoms),
- atoms->atomCompoundText,
- atoms->atomLocalProperty,
- iWindow, CurrentTime);
- if (iReturn == BadAtom || iReturn == BadWindow) {
- ErrorF("winClipboardWindowProc - WM_RENDER*FORMAT - "
- "XConvertSelection () failed\n");
- break;
+ selection = winClipboardGetLastOwnedSelectionAtom(atoms);
+ if (selection == None) {
+ ErrorF("winClipboardWindowProc - no monitored selection is owned\n");
+ goto fake_paste;
}
- /* Special handling for WM_RENDERALLFORMATS */
- if (message == WM_RENDERALLFORMATS) {
- /* We must open and empty the clipboard */
+ winDebug("winClipboardWindowProc - requesting targets for selection from owner\n");
- /* Close clipboard if we have it open already */
- if (GetOpenClipboardWindow() == hwnd) {
- CloseClipboard();
- }
+ /* Request the selection's supported conversion targets */
+ XConvertSelection(pDisplay,
+ selection,
+ atoms->atomTargets,
+ atoms->atomLocalProperty,
+ iWindow, CurrentTime);
- if (!OpenClipboard(hwnd)) {
- ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
- "OpenClipboard () failed: %08x\n",
- GetLastError());
- break;
- }
+ /* Process X events */
+ data.fUseUnicode = fConvertToUnicode;
+ iReturn = winProcessXEventsTimeout(hwnd,
+ iWindow,
+ pDisplay,
+ &data,
+ atoms,
+ WIN_POLL_TIMEOUT);
- if (!EmptyClipboard()) {
- ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
- "EmptyClipboard () failed: %08x\n",
- GetLastError());
- break;
- }
+ if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) {
+ ErrorF
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n");
+ goto fake_paste;
}
- /* Process the SelectionNotify event */
+ /* Choose the most preferred target */
+ {
+ struct target_priority
+ {
+ Atom target;
+ unsigned int priority;
+ };
+
+ struct target_priority target_priority_table[] =
+ {
+ { atoms->atomCompoundText, 0 },
+#ifdef X_HAVE_UTF8_STRING
+ { atoms->atomUTF8String, 1 },
+#endif
+ { XA_STRING, 2 },
+ };
+
+ int best_priority = INT_MAX;
+
+ int i,j;
+ for (i = 0 ; data.targetList[i] != 0; i++)
+ {
+ for (j = 0; j < sizeof(target_priority_table)/sizeof(struct target_priority); j ++)
+ {
+ if ((data.targetList[i] == target_priority_table[j].target) &&
+ (target_priority_table[j].priority < best_priority))
+ {
+ best_target = target_priority_table[j].target;
+ best_priority = target_priority_table[j].priority;
+ }
+ }
+ }
+ }
+
+ free(data.targetList);
+ data.targetList = 0;
+
+ winDebug("winClipboardWindowProc - best target is %d\n", best_target);
+
+ /* No useful targets found */
+ if (best_target == 0)
+ goto fake_paste;
+
+ winDebug("winClipboardWindowProc - requesting selection from owner\n");
+
+ /* Request the selection contents */
+ XConvertSelection(pDisplay,
+ selection,
+ best_target,
+ atoms->atomLocalProperty,
+ iWindow, CurrentTime);
+
+ /* Process X events */
iReturn = winProcessXEventsTimeout(hwnd,
iWindow,
pDisplay,
- fConvertToUnicode,
+ &data,
atoms,
WIN_POLL_TIMEOUT);
/*
- * The last call to winProcessXEventsTimeout
- * from above had better have seen a notify event, or else we
- * are dealing with a buggy or old X11 app. In these cases we
- * have to paste some fake data to the Win32 clipboard to
- * satisfy the requirement that we write something to it.
+ * winProcessXEventsTimeout had better have seen a notify event,
+ * or else we are dealing with a buggy or old X11 app.
*/
- if (WIN_XEVENTS_NOTIFY != iReturn) {
- /* Paste no data, to satisfy required call to SetClipboardData */
- SetClipboardData(CF_UNICODETEXT, NULL);
- SetClipboardData(CF_TEXT, NULL);
-
+ if (WIN_XEVENTS_NOTIFY_DATA != iReturn) {
ErrorF
- ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n");
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n");
}
-
- /* Special handling for WM_RENDERALLFORMATS */
- if (message == WM_RENDERALLFORMATS) {
- /* We must close the clipboard */
-
- if (!CloseClipboard()) {
- ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - "
- "CloseClipboard () failed: %08x\n",
- GetLastError());
- break;
- }
+ else {
+ pasted = TRUE;
}
- winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
+ /*
+ * If we couldn't get the data from the X clipboard, we
+ * have to paste some fake data to the Win32 clipboard to
+ * satisfy the requirement that we write something to it.
+ */
+ fake_paste:
+ if (!pasted)
+ {
+ /* Paste no data, to satisfy required call to SetClipboardData */
+ SetClipboardData(CF_UNICODETEXT, NULL);
+ SetClipboardData(CF_TEXT, NULL);
+ }
+
+ winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n");
return 0;
}
}
diff --git a/xorg-server/hw/xwin/winclipboard/xevents.c b/xorg-server/hw/xwin/winclipboard/xevents.c
index 33d52aafd..835195b52 100644
--- a/xorg-server/hw/xwin/winclipboard/xevents.c
+++ b/xorg-server/hw/xwin/winclipboard/xevents.c
@@ -43,11 +43,15 @@
#undef _XSERVER64
#endif
-#include "internal.h"
+#include <limits.h>
+#include <wchar.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xfixes.h>
+#include "winclipboard.h"
+#include "internal.h"
+
/*
* Constants
*/
@@ -62,6 +66,7 @@
*/
extern int xfixes_event_base;
+Bool fPrimarySelection = TRUE;
/*
* Local variables
@@ -133,13 +138,59 @@ winClipboardInitMonitoredSelections(void)
lastOwnedSelectionIndex = CLIP_OWN_NONE;
}
+static int
+winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
+{
+ Atom type;
+ int format;
+ unsigned long nitems;
+ unsigned long after;
+ Atom *prop;
+
+ /* Retrieve the selection data and delete the property */
+ int iReturn = XGetWindowProperty(pDisplay,
+ iWindow,
+ atoms->atomLocalProperty,
+ 0,
+ INT_MAX,
+ True,
+ AnyPropertyType,
+ &type,
+ &format,
+ &nitems,
+ &after,
+ (unsigned char **)&prop);
+ if (iReturn != Success) {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ "XGetWindowProperty () failed, aborting: %d\n", iReturn);
+ } else {
+ int i;
+ data->targetList = malloc((nitems+1)*sizeof(Atom));
+
+ for (i = 0; i < nitems; i++)
+ {
+ Atom atom = prop[i];
+ char *pszAtomName = XGetAtomName(pDisplay, atom);
+ data->targetList[i] = atom;
+ winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %d = %s\n", i, atom, pszAtomName);
+ XFree(pszAtomName);
+ }
+
+ data->targetList[nitems] = 0;
+
+ XFree(prop);
+ }
+
+ return WIN_XEVENTS_NOTIFY_TARGETS;
+}
+
/*
* Process any pending X events
*/
int
winClipboardFlushXEvents(HWND hwnd,
- Window iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms)
+ Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
{
Atom atomClipboard = atoms->atomClipboard;
Atom atomLocalProperty = atoms->atomLocalProperty;
@@ -158,14 +209,11 @@ winClipboardFlushXEvents(HWND hwnd,
int iReturn;
HGLOBAL hGlobal = NULL;
XICCEncodingStyle xiccesStyle;
- int iConvertDataLen = 0;
char *pszConvertData = NULL;
char *pszTextList[2] = { NULL };
int iCount;
char **ppszTextList = NULL;
wchar_t *pwszUnicodeStr = NULL;
- int iUnicodeLen = 0;
- int iReturnDataLen = 0;
Bool fAbort = FALSE;
Bool fCloseClipboard = FALSE;
Bool fSetClipboardData = TRUE;
@@ -272,7 +320,7 @@ winClipboardFlushXEvents(HWND hwnd,
fCloseClipboard = TRUE;
/* Check that clipboard format is available */
- if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+ if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
static int count; /* Hack to stop acroread spamming the log */
static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
@@ -289,7 +337,7 @@ winClipboardFlushXEvents(HWND hwnd,
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
- else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
+ else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
"available from Win32 clipboard. Aborting.\n");
@@ -311,7 +359,7 @@ winClipboardFlushXEvents(HWND hwnd,
xiccesStyle = XStringStyle;
/* Get a pointer to the clipboard text, in desired format */
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
/* Retrieve clipboard data */
hGlobal = GetClipboardData(CF_UNICODETEXT);
}
@@ -330,8 +378,8 @@ winClipboardFlushXEvents(HWND hwnd,
pszGlobalData = (char *) GlobalLock(hGlobal);
/* Convert the Unicode string to UTF8 (MBCS) */
- if (fUseUnicode) {
- iConvertDataLen = WideCharToMultiByte(CP_UTF8,
+ if (data->fUseUnicode) {
+ int iConvertDataLen = WideCharToMultiByte(CP_UTF8,
0,
(LPCWSTR) pszGlobalData,
-1, NULL, 0, NULL, NULL);
@@ -346,7 +394,6 @@ winClipboardFlushXEvents(HWND hwnd,
}
else {
pszConvertData = strdup(pszGlobalData);
- iConvertDataLen = strlen(pszConvertData) + 1;
}
/* Convert DOS string to UNIX string */
@@ -361,7 +408,7 @@ winClipboardFlushXEvents(HWND hwnd,
xtpText.nitems = 0;
/* Create the text property from the text list */
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
iReturn = Xutf8TextListToTextProperty(pDisplay,
pszTextList,
@@ -491,7 +538,6 @@ winClipboardFlushXEvents(HWND hwnd,
*/
case SelectionNotify:
-
winDebug("winClipboardFlushXEvents - SelectionNotify\n");
{
char *pszAtomName;
@@ -506,75 +552,31 @@ winClipboardFlushXEvents(HWND hwnd,
}
/*
- * Request conversion of UTF8 and CompoundText targets.
- */
- if (event.xselection.property == None) {
- if (event.xselection.target == XA_STRING) {
- winDebug("winClipboardFlushXEvents - SelectionNotify - "
- "XA_STRING\n");
+ SelectionNotify with property of None indicates either:
- return WIN_XEVENTS_CONVERT;
- }
- else if (event.xselection.target == atomUTF8String) {
- winDebug("winClipboardFlushXEvents - SelectionNotify - "
- "Requesting conversion of UTF8 target.\n");
-
- XConvertSelection(pDisplay,
- event.xselection.selection,
- XA_STRING,
- atomLocalProperty, iWindow, CurrentTime);
-
- /* Process the ConvertSelection event */
- XFlush(pDisplay);
- return WIN_XEVENTS_CONVERT;
- }
-#ifdef X_HAVE_UTF8_STRING
- else if (event.xselection.target == atomCompoundText) {
- winDebug("winClipboardFlushXEvents - SelectionNotify - "
- "Requesting conversion of CompoundText target.\n");
-
- XConvertSelection(pDisplay,
- event.xselection.selection,
- atomUTF8String,
- atomLocalProperty, iWindow, CurrentTime);
-
- /* Process the ConvertSelection event */
- XFlush(pDisplay);
- return WIN_XEVENTS_CONVERT;
- }
-#endif
- else {
+ (i) Generated by the X server if no owner for the specified selection exists
+ (perhaps it's disappeared on us mid-transaction), or
+ (ii) Sent by the selection owner when the requested selection conversion could
+ not be performed or server errors prevented the conversion data being returned
+ */
+ if (event.xselection.property == None) {
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
- "Unknown format. Cannot request conversion, "
- "aborting.\n");
- break;
+ "Conversion to format %d refused.\n",
+ event.xselection.target);
+ return WIN_XEVENTS_FAILED;
}
- }
- /* Retrieve the size of the stored data */
- iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0, /* Don't get data, just size */
- False,
- AnyPropertyType,
- &xtpText.encoding,
- &xtpText.format,
- &xtpText.nitems,
- &ulReturnBytesLeft, &xtpText.value);
- if (iReturn != Success) {
- ErrorF("winClipboardFlushXEvents - SelectionNotify - "
- "XGetWindowProperty () failed, aborting: %d\n", iReturn);
- break;
+ if (event.xselection.target == atomTargets) {
+ return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms);
}
- winDebug("SelectionNotify - returned data %d left %d\n",
- xtpText.nitems, ulReturnBytesLeft);
-
- /* Request the selection data */
+ /* Retrieve the selection data and delete the property */
iReturn = XGetWindowProperty(pDisplay,
iWindow,
atomLocalProperty,
0,
- ulReturnBytesLeft,
- False,
+ INT_MAX,
+ True,
AnyPropertyType,
&xtpText.encoding,
&xtpText.format,
@@ -583,7 +585,7 @@ winClipboardFlushXEvents(HWND hwnd,
if (iReturn != Success) {
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
- break;
+ goto winClipboardFlushXEvents_SelectionNotify_Done;
}
{
@@ -597,7 +599,7 @@ winClipboardFlushXEvents(HWND hwnd,
pszAtomName = NULL;
}
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
/* Convert the text property to a text list */
iReturn = Xutf8TextPropertyToTextList(pDisplay,
@@ -614,8 +616,7 @@ winClipboardFlushXEvents(HWND hwnd,
/* Conversion succeeded or some unconvertible characters */
if (ppszTextList != NULL) {
int i;
-
- iReturnDataLen = 0;
+ int iReturnDataLen = 0;
for (i = 0; i < iCount; i++) {
iReturnDataLen += strlen(ppszTextList[i]);
}
@@ -664,14 +665,14 @@ winClipboardFlushXEvents(HWND hwnd,
/* Convert the X clipboard string to DOS format */
winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
- if (fUseUnicode) {
+ if (data->fUseUnicode) {
/* Find out how much space needed to convert MBCS to Unicode */
- iUnicodeLen = MultiByteToWideChar(CP_UTF8,
+ int iUnicodeLen = MultiByteToWideChar(CP_UTF8,
0,
pszReturnData, -1, NULL, 0);
- /* Allocate memory for the Unicode string */
- pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
+ /* NOTE: iUnicodeLen includes space for null terminator */
+ pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen);
if (!pwszUnicodeStr) {
ErrorF("winClipboardFlushXEvents - SelectionNotify "
"malloc failed for pwszUnicodeStr, aborting.\n");
@@ -689,9 +690,10 @@ winClipboardFlushXEvents(HWND hwnd,
/* Allocate global memory for the X clipboard data */
hGlobal = GlobalAlloc(GMEM_MOVEABLE,
- sizeof(wchar_t) * (iUnicodeLen + 1));
+ sizeof(wchar_t) * iUnicodeLen);
}
else {
+ int iConvertDataLen = 0;
pszConvertData = strdup(pszReturnData);
iConvertDataLen = strlen(pszConvertData) + 1;
@@ -723,9 +725,8 @@ winClipboardFlushXEvents(HWND hwnd,
}
/* Copy the returned string into the global memory */
- if (fUseUnicode) {
- memcpy(pszGlobalData,
- pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1));
+ if (data->fUseUnicode) {
+ wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr);
free(pwszUnicodeStr);
pwszUnicodeStr = NULL;
}
@@ -740,7 +741,7 @@ winClipboardFlushXEvents(HWND hwnd,
pszGlobalData = NULL;
/* Push the selection data to the Windows clipboard */
- if (fUseUnicode)
+ if (data->fUseUnicode)
SetClipboardData(CF_UNICODETEXT, hGlobal);
else
SetClipboardData(CF_TEXT, hGlobal);
@@ -770,7 +771,7 @@ winClipboardFlushXEvents(HWND hwnd,
SetClipboardData(CF_UNICODETEXT, NULL);
SetClipboardData(CF_TEXT, NULL);
}
- return WIN_XEVENTS_NOTIFY;
+ return WIN_XEVENTS_NOTIFY_DATA;
case SelectionClear:
winDebug("SelectionClear - doing nothing\n");
@@ -790,7 +791,7 @@ winClipboardFlushXEvents(HWND hwnd,
winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
/* Save selection owners for monitored selections, ignore other selections */
- if (e->selection == XA_PRIMARY) {
+ if ((e->selection == XA_PRIMARY) && fPrimarySelection) {
MonitorSelection(e, CLIP_OWN_PRIMARY);
}
else if (e->selection == atomClipboard) {
diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.c b/xorg-server/hw/xwin/winclipboard/xwinclip.c
index 3677974c4..856c4dd54 100644
--- a/xorg-server/hw/xwin/winclipboard/xwinclip.c
+++ b/xorg-server/hw/xwin/winclipboard/xwinclip.c
@@ -92,6 +92,13 @@ main (int argc, char *argv[])
continue;
}
+ /* Look for -noprimary */
+ if (!strcmp (argv[i], "-noprimary"))
+ {
+ fPrimarySelection = False;
+ continue;
+ }
+
/* Yack when we find a parameter that we don't know about */
printf ("Unknown parameter: %s\nExiting.\n", argv[i]);
exit (1);
diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.man b/xorg-server/hw/xwin/winclipboard/xwinclip.man
index 822db91d4..a53dc3029 100644
--- a/xorg-server/hw/xwin/winclipboard/xwinclip.man
+++ b/xorg-server/hw/xwin/winclipboard/xwinclip.man
@@ -29,6 +29,9 @@ Specifies the X server display to connect to.
.TP 8
.B \-nounicodeclipboard
Do not use unicode text on the clipboard.
+.TP 8
+.B \-noprimary
+Do not monitor the PRIMARY selection.
.SH "SEE ALSO"
XWin(1)
diff --git a/xorg-server/hw/xwin/winclipboardwrappers.c b/xorg-server/hw/xwin/winclipboardwrappers.c
index 2679f4f98..2e6b63287 100644
--- a/xorg-server/hw/xwin/winclipboardwrappers.c
+++ b/xorg-server/hw/xwin/winclipboardwrappers.c
@@ -44,12 +44,6 @@
DISPATCH_PROC(winProcEstablishConnection);
/*
- * References to external symbols
- */
-
-extern Bool g_fClipboard;
-
-/*
* Wrapper for internal EstablishConnection function.
* Initializes internal clients that must not be started until
* an external client has connected.
diff --git a/xorg-server/hw/xwin/winprocarg.c b/xorg-server/hw/xwin/winprocarg.c
index f2bf05bad..e8cccb4c2 100644
--- a/xorg-server/hw/xwin/winprocarg.c
+++ b/xorg-server/hw/xwin/winprocarg.c
@@ -37,13 +37,8 @@ from The Open Group.
#include "winmsg.h"
#include "winmonitors.h"
-/*
- * References to external symbols
- */
-
#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboard;
+#include "winclipboard/winclipboard.h"
#endif
/*
@@ -716,6 +711,26 @@ ddxProcessArgument(int argc, char *argv[], int i)
/* Indicate that we have processed this argument */
return 1;
}
+
+ /*
+ * Look for the '-primary' argument
+ */
+ if (IS_OPTION("-primary")) {
+ fPrimarySelection = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-noprimary' argument
+ */
+ if (IS_OPTION("-noprimary")) {
+ fPrimarySelection = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
#endif
/*
diff --git a/xorg-server/hw/xwin/winresource.h b/xorg-server/hw/xwin/winresource.h
index afbf9f28d..37e92ce61 100644
--- a/xorg-server/hw/xwin/winresource.h
+++ b/xorg-server/hw/xwin/winresource.h
@@ -43,6 +43,7 @@
#define ID_APP_HIDE_ROOT 201
#define ID_APP_ALWAYS_ON_TOP 202
#define ID_APP_ABOUT 203
+#define ID_APP_MONITOR_PRIMARY 204
#define ID_ABOUT_WEBSITE 303
diff --git a/xorg-server/hw/xwin/wintrayicon.c b/xorg-server/hw/xwin/wintrayicon.c
index e0aa7e5ab..6acc0d712 100644
--- a/xorg-server/hw/xwin/wintrayicon.c
+++ b/xorg-server/hw/xwin/wintrayicon.c
@@ -32,9 +32,13 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include <shellapi.h>
#include "winprefs.h"
+#ifdef XWIN_CLIPBOARD
+#include "winclipboard/winclipboard.h"
+#endif
/*
* Initialize the tray icon
@@ -170,6 +174,21 @@ winHandleIconMessage(HWND hwnd, UINT message,
RemoveMenu(hmenuTray, ID_APP_HIDE_ROOT, MF_BYCOMMAND);
}
+#ifdef XWIN_CLIPBOARD
+ if (g_fClipboard) {
+ /* Set menu state to indicate if 'Monitor Primary' is enabled or not */
+ MENUITEMINFO mii = { 0 };
+ mii.cbSize = sizeof(MENUITEMINFO);
+ mii.fMask = MIIM_STATE;
+ mii.fState = fPrimarySelection ? MFS_CHECKED : MFS_UNCHECKED;
+ SetMenuItemInfo(hmenuTray, ID_APP_MONITOR_PRIMARY, FALSE, &mii);
+ }
+ else {
+ /* Remove 'Monitor Primary' menu item */
+ RemoveMenu(hmenuTray, ID_APP_MONITOR_PRIMARY, MF_BYCOMMAND);
+ }
+#endif
+
SetupRootMenu(hmenuTray);
/*
diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c
index 0c434c927..1bf3f5cde 100644
--- a/xorg-server/hw/xwin/winwndproc.c
+++ b/xorg-server/hw/xwin/winwndproc.c
@@ -1218,6 +1218,12 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
#endif
+#ifdef XWIN_CLIPBOARD
+ case ID_APP_MONITOR_PRIMARY:
+ fPrimarySelection = !fPrimarySelection;
+ return 0;
+#endif
+
case ID_APP_ABOUT:
/* Display the About box */
winDisplayAboutDialog(s_pScreenPriv);